Rotated images and directions

Blitz3D Forums/Blitz3D Beginners Area/Rotated images and directions

Valgar(Posted 2009) [#1]
Hello everyone
I am trying to write a code that move enemies across a path.
Everything works ok.
but it look unnatural because the images are always the same direction.
So i have made an array and stored into it the different images (the difference is 30 degrees from eachother,so i have a total of 12 images).
What i dont understand is how i can write a code that display the right frame!
In the movement function i have "angle=atan2 (newy-oldy,newx-oldx)"
so the enemy have the correct direction between the old point and the new one...
But i screw with the next code that choose the image based on that angle.
If ang=0 And ang<30 Then nemico=enemy(1)
If ang=30 And ang<60 Then nemico=enemy(2)
If ang=60 And ang<90 Then nemico=enemy(3)
If ang=90 And ang<120 Then nemico=enemy(4)
If ang=120 And ang<150 Then nemico=enemy(5)
If ang=150 And ang<180 Then nemico=enemy(6)
If ang=180 And ang> -150 Then nemico=enemy(7)
If ang= -150 And ang> -120 Then nemico=enemy(8)
If ang= -120 And ang> -90 Then nemico=enemy(9)
If ang= -90 And ang> -60 Then nemico=enemy(10)
If ang= -60 And ang> -30 Then nemico=enemy(11)
If ang= -30 And ang<0 Then nemico=enemy(12)
DrawImage nemico,ex,ey

I get image doesnt exist,because it cant detect the angle properly.
Do you know where i make the error?
And if theres a better way to sort the image out instead of using all those if's?
Thanks in advance


Guy Fawkes(Posted 2009) [#2]
there's no way to get rid of the Ifs, but did you try rotateimage?


Valgar(Posted 2009) [#3]
Yes.
Every image is properly rotated and stored in the array.
I suppose the error is in the logic of the is's,because i had put a debuglog for the angle and its calculated properly.


Floyd(Posted 2009) [#4]
First adjust the angle so the range is 0 to 360 instead of -180 to 180:

ang = ( ( ang mod 360 ) + 360 ) Mod 360

Dividing by 30 gives values 0,1...11. Then add 1 to get 1,2...12.

n is an Integer variable:

n = Int( ang ) / 30 + 1

If the images were stored in enemy(0) to enemy(11) then you would not need the " + 1 " at the end.

Also, you may not need the first "Mod 360", but it doen't do any harm. I'm not sure what values ang may have. If it could be less than -180 then the extra Mod 360 is important.


Yasha(Posted 2009) [#5]
Couple of things:

- You're testing If ang = X And ang > Y. Shouldn't this be If ang < X And ang > Y? Checking equality first means that the second half of the expression is irrelevant, and angles in between those marks won't register at all. You also probably also ought to change one of those to a <= or >= so that the exact value also registers.

- You can use a Select/Case structure or If/ElseIf to only check values until the right one is found. If/ElseIf is easier to nest for things like binary chopping and is also slightly faster (I dimly remember testing it once, could be totally off here), but Select/Case looks very neat and tidy on screen.


Floyd(Posted 2009) [#6]
The = should be >= in the various If tests.

But the right way is to get rid of all of them and simply calculate n from ang.


Valgar(Posted 2009) [#7]
Oh thank you!
I adjusted the code to have a 360 scale and stored the result in a variable that i change based on the angle.
Now i just need to let the code know that the frame change just if the object is moving (at the moment when the object stop moving it return to position 0 because the angle is 0...)


_PJ_(Posted 2009) [#8]
Why not just use:
Loal n%=nemico=enemy(((Int(( ( ang Mod 360 ) + 180 ) Mod 360) )Shr 5) +1)



Valgar(Posted 2009) [#9]
Do you mean:
local nemico%=enemy(((Int(( ( ang Mod 360 ) + 180 ) Mod 360) )Shr 5) +1)

If so the enemy image is rotated somehow in a wrong angle.
Also i understand the code until the shr 5 (that means that the value is shifted 5 times...so the result is 32 i think {not 30}) but why the "+1" ?
The images are already rotated in the right way and stored in an array(called enemy("number of rotations"..i use "nemico" just because its easier to type that in the drawimage command).


_PJ_(Posted 2009) [#10]
Sorry, then:

nemico%=enemy(((Int(( ( ang Mod 360 ) + 180 ) Mod 360) )Shr 4) +1)


Shr 4 divides by 16 Giving an Integer result of 0 to 11
The +1 simply adjusts this to make 1 to 12

If the angles are off, then it's because the iages don;t correspond to the angles initially, i.e. image enemy(1) does not represent 0 to 30 degrees.

therefore, an adjustment will be needed of 'whatever' which is a number of 1-29.

nemico=enemy(((((Int(( ( ang Mod 360 ) + 180 ) Mod 360) )Shr 4) +whatever) Mod 30 ) +1)



Valgar(Posted 2009) [#11]
Ok thank you.
I got everything working (except the "don't return back to angle 0 if you don't have anymore waypoints to make the direction" but i think i can fix it with another variable).
Still look a bit plastic though(maybe cause theres no acceleration yet)...but i think a shoot-em-up doesn't need that level of attention.
Thanks a lot


Stevie G(Posted 2009) [#12]
You want something like the below so that inbetween angles display the best fit image. e.g. the image will still be 0 if the angle is between -165 and 15

Function ANGLE( ANG# , Segs )
			
	Local Div# = 360.0 / Segs
	
	If ANG < 0 ANG = 360 + ANG
	Return Floor( ( ( ANG + Div*.5 ) Mod 360 ) / Div )				
				
End Function


ImageToDisplay = ANGLE( ang, 12 ) + 1



Valgar(Posted 2009) [#13]
Humm...getting mad now.
I ditched my code because was making water from every hole...i am trying to adapt one in the code archive from Ross C.
Everything work ok but just if i use the suggestion from Floyd...also i am making a bigger array (360) because the previous one wasnt working at all.
Still the "return to start position because the angle is 0" (basicly the final direction when no other waypoints exist) persist,because i dont understand Stevie G hint (sorry but my math skills are very limited...)
Here the code (remember to change the image if you want to run it):

I really dont want such a big array,but for some strange reason anything smaller make weird results (the ideal would be 10 or similar frames)


Valgar(Posted 2009) [#14]
I managed to make a variation based on Stevie G suggestions.it work ok.
Just have to find out a way to tell the object to not change direction at the end.


Stevie G(Posted 2009) [#15]
Post your code.


Valgar(Posted 2009) [#16]
Ok.
Its basically the same as before...

Max path points its 100....to test you can just set it smaller like 20.
I would like the last waypoints to retain the object direction instead of resetting it to the original point (0 degrees).


Guy Fawkes(Posted 2009) [#17]
what you do with that is save the x and y rotation of the object's direction to an encrypted file, call this function savefile(waypoint_file$), then u simply load it from loadfile(waypoint_file$), then u simply read from the line of that certain rotation from the file, and repeat as needed :)


Valgar(Posted 2009) [#18]
I am already making a savefile function (have to debug it,cause for some strange reason my "for----->next" loop write just half of the coordinates(???) and the result change everytime i load it) but i am sure it can be sorted with a condition between waypoints (like "if last waypoint then direction=last direction" etc etc) i just suck at writing down my ideas,because even if they make sense when i write down the pseudocode,the actual code doesnt work hehe


Valgar(Posted 2009) [#19]
I have solved the problem,was pretty simple (dont know what i was thinking when coding hehe).
I just had to save the directions into an array, and then put another condition into my code to check "ang" value.
Example:
If ang=0
		dir=max_path_points-1
	Else 
		dir=current_path
		direction(dir)=anglez(ang,36)	;find the right frame to display based on the angle
EndIf
DrawImage enemy(direction(dir)),ex,ey

Sometimes the solution is so simple that we can't see it and we make things overcomplicated...
Thanks everyone for the help!