## Beginners math-question on movement. (trigonometry)

Fruity
Unregistered

Post: #1
Let me first say that I've searched the archive for this, but couldn't seem to find anything on the subject.

I'm a beginner with programming games, and downloaded the BlitzMax-demo a couple of days ago. I'm trying to figure out some things about movement, on a very simple project.

I have a white dot, and that's all I have. When I click somewhere on the screen, I want the dot to move to that location at a set speed. So what I need is to first find out the angle which it will follow, and then I have to make it go at the same speed for every kinds of angles. (If it moves 0 degrees at a speed of X=X+100 per second, it should move 45 degrees at a speed X=X+(somewhat less than 100), for it to look right.)

After giving this problem quite a bit of thought (several years since I learned this stuff in mathematics-class, and I can't find my old books telling me how to do it), I think I may have remembered what I need. I just thought I'd ask you to look over it and tell me if I have forgotten something..

-------------------
The white dot is at (X0,Y0).
The point it will go to is (X1,Y1).

To find the angle between these points I will first have to check where the new location is, compared to the other. In my thoughts I draw an imaginary triangle, with angles A,B and C, and opposing sides a,b and c. Angle B is at the point (X0,Y0), angle A is 90 degrees, angle C is at the point (X1,Y1). (I snatched a pic from the internet that might make things clearer.)

There are four possibilities:
• X1 > X0 and Y1 > Y0.
• X1 < X0 and Y1 > Y0.
• X1 < X0 and Y1 < Y0.
• X1 > X0 and Y1 < Y0.

Depending on this, there are four ways to calculate the angles:
• If X1 > X0 and Y1 > Y0.

To find the angle B we use tan-1 (b/c) (inverse tangent(spelling?))
• X1 < X0 and Y1 > Y0.

To find the angle B we use 90deg - tan-1 (b/c)
• X1 < X0 and Y1 < Y0.

To find the angle B we use 180deg + tan-1 (b/c)
• X1 > X0 and Y1 < Y0.

To find the angle B we use 270deg - tan-1 (b/c)

------------------------------------------------------------------------

Now that I have found the angle, the rest should be easy.
To find the value for movement in X-direction, I multiply the speed-variable with cos (degrees).
To find the value for movement in Y-direction, I multiply the speed-variable with sin (degrees).

Using Cos and Sin, I know that the length it will travel on screen / timeunit is the same no matter what direction it is heading.

------------------------------------------------------------------------

If you read through all of this, did you see any apparent errors or flaws in my thinking? I want to get this straight in my head before I translate it into BlitzMax-code.
Oh, and in BlitzMax, Y increases downwards and not upwards, but I can't see why that should make any difference to my thinking. Please do correct me if I'm wrong.
Fruity
Unregistered

Post: #2
Reading through this yet another time, I see I've forgotten some things.
• X1 = X0 and Y1 = Y0

Do nothing, end movement loop.
• X1 = X0 and Y1 > Y0

Set degrees-variable to 90
• X1 = X0 and Y1 < Y0

Set degrees-variable to 270
• X1 > X0 and Y1 = Y0

Set degrees-variable to 0. (or 360)
• X1 < X0 and Y1 = Y0

Set degrees-variable to 180.

------------------------------------------------
For now, these are the errors I can see with my initial thinking. Sorry to make two posts out of it in such a short time.
Moderator
Posts: 1,563
Joined: 2003.10
Post: #3

- Alex Diener
Fruity
Unregistered

Post: #4

- Alex Diener

Thanks for the link, it helped a lot. I guess that means that my method will work totally ok, but that it also can be done as easily as:

magnitude = X*X + Y*Y

if magnitude = 0 end movement loop

magnitude = sqrt(magnitude)

X = X/ magnitude
Y = Y/ magnitude

This should definitely make the code a lot easier and more understandable. Thanks!

Edit: checked it for a couple of different points. Yup, works fine. Outputs the same numbers as it did with sin/cos method.
Member
Posts: 41
Joined: 2005.02
Post: #5
Fruity Wrote:Edit: checked it for a couple of different points. Yup, works fine. Outputs the same numbers as it did with sin/cos method.

Vector math is normally a lot faster than using sine and cosine as well. Of course, when you are just learning speed isn't always the issue until it works, but it helps
Fruity
Unregistered

Post: #6
iefan Wrote:Vector math is normally a lot faster than using sine and cosine as well. Of course, when you are just learning speed isn't always the issue until it works, but it helps

Yeah. It was definitely much faster. I'll remember this way of doing it in the future.

If anyone is interested, this is what the BlitzCode looked like:
(I had to to quite an amount of debugging and reading before I could understand the the function Randomize wouldn't return floating variables. I wonder how people manage debugging in the more difficult areas.. well.. a time for everything.)

Code:
```Graphics 800,600 'set resolution, fullscreen x#=500;y#=500 'start location, float variables speed%=1 'determines at what speed it will go, integer variables '---------------start of main loop------------------ While Not KeyDown(key_escape) 'start main loop     Plot x,y 'plot the white dot we will move around     'get mouse-coordinates. Send them + dot-coords to Normalize-function:     If KeyHit(key_mouseleft) x1=MouseX();y1=MouseY();Xdir#=Normalize(x1-x,y1-y);Ydir#=Normalize(y1-y,x1-x)     x:+speed*Xdir 'increase/decrease X, go right/left     y:+speed*Ydir 'increase/decrease Y, go down/up                  a%=x1-x                'This is the stop-code. First we input the difference between target and position     b%=y1-y                'into an integer, then we check if this integer = 0.     If a=0 Then Xdir=0    'I really wanted to do it without extra variables, like If 1>(x1-x)>(-1) then...     If b=0 Then Ydir=0    'but I couldn't get it to work properly.          Flip;Cls 'show backbuffer on screen;clear backbuffer. Wend 'end of main loop, go to beginning '---------------end of main loop------------------ Function Normalize#(A%,B%) 'a function called from the main loop         Magnitude2%=(a*a)+(b*b)         If Magnitude2=0 Return 0 'no hero divides by zero         Magnitude#=Sqr(Magnitude2)         Return A/Magnitude 'return directional value End Function```

Now I'll have to look into rotating of some kind of spaceship. I see that was also covered on the article that ThemsAllTook gave me. Thanks again. This is fun!
Member
Posts: 198
Joined: 2005.01
Post: #7
And if you're getting into rotation, you might want to just go ahead and look up doing this stuff with matrices. They're really simple to set up and suddenly pretty much any transformation seems easy. And fast, too, since you can do all your "hard" operations once and then apply them to N vertices at a constant time per vertex.

Cryptic Allusion Games / Cryptic Allusion, LLC
http://www.cagames.com/
Fruity
Unregistered

Post: #8
Dan Potter Wrote:And if you're getting into rotation, you might want to just go ahead and look up doing this stuff with matrices. They're really simple to set up and suddenly pretty much any transformation seems easy. And fast, too, since you can do all your "hard" operations once and then apply them to N vertices at a constant time per vertex.

Don't have any clue what it is, but I'll look it up in Google. Thanks.
For now I just use the command ATan2(Ydir,Xdir) which is the inverse tangent of two variables, the Y-direction and X-direction calculated for movement speed.

My first goal now will be to transform my code so that I have a Type called SpaceShip with information like acceleration, max-speed, breaks, turning (how many degrees it will turn per time-unit). This way it will look more natural, and making it object oriented will make it easy to manage more ships on the screen at the same time.. But I guess this is getting of topic for this board. Sorry.

Edit: I had a look at rotational matrices, and I think I'll let it be for now, as I didn't see any apparent pros compared to the method I use now, as long as I don't do it in 3d. Anything I missed on this?
Member
Posts: 304
Joined: 2002.04
Post: #9
you seem to have gotten it! No - if this is 2d and you only care about rotations and translations you dont need to worry about matrices.

you probably should change:

if magnitude = 0 end movement loop

to:

if magnitude < some_very_small_number end movement loop

since magnitude will rarely equal exactly 0 (I assume these are floating point variables?)

Fruity
Unregistered

Post: #10
codemattic Wrote:you seem to have gotten it! No - if this is 2d and you only care about rotations and translations you dont need to worry about matrices.

you probably should change:

if magnitude = 0 end movement loop

to:

if magnitude < some_very_small_number end movement loop

since magnitude will rarely equal exactly 0 (I assume these are floating point variables?)

They are calculated by pixels on screen, in a 800*600 grid, so I doubt it is neccessary. (spelling?) I'll try and rememeber it if I ever do something w/floating point, tho..
Moderator
Posts: 529
Joined: 2003.03
Post: #11
Fruity Wrote:Oh, and in BlitzMax, Y increases downwards and not upwards, but I can't see why that should make any difference to my thinking. Please do correct me if I'm wrong.

Quite a few computer graphics systems do it that way. Its probably easier to do all your calculations as it positive y were up, and then just mirror everything around the bottom of the screen when it comes time to draw.

position.y=screenheight-position.y or something like that.

"Yes, well, that's the sort of blinkered, Philistine pig-ignorance I've come to expect from you non-creative garbage."
Member
Posts: 198
Joined: 2005.01
Post: #12
codemattic Wrote:No - if this is 2d and you only care about rotations and translations you dont need to worry about matrices.

Technically if it's 3D you don't need to worry about matrices either. Before I learned them in the past I wrote 3D systems for DOS that used only sin/cos and lots of multiplies and divides to do all the standard transforms (rotation, scaling, transform, perspective, etc). The problem just becomes so much simpler with them, and you don't have to understand why they work to use them effectively. It's certainly doable the way Fruity's doing it without too much trouble. It could be a good excuse to learn how to use matrix math though since it's used pretty much everywhere in graphics these days. Almost any application of GL will have you touching matrices if only through glTranslate and such.

Cryptic Allusion Games / Cryptic Allusion, LLC
http://www.cagames.com/
Fruity
Unregistered

Post: #13
Dan Potter Wrote:It could be a good excuse to learn how to use matrix math though since it's used pretty much everywhere in graphics these days. Almost any application of GL will have you touching matrices if only through glTranslate and such.

I'll definitely look into it later, but there's just so much different stuff I can learn right now, so I try to be a bit selective as to what to learn first.

After all, I've only got 25 days left of the BlitzMax-demo, and I cannot buy the full version yet, so I want to try to come up with something reasonable within that time-frame. (I guess I should just spend the time trying to learn as much as possible, but if I can finish something it will definitely be a motivating factor for later. )
Member
Posts: 198
Joined: 2005.01
Post: #14
Good point Best to stick with the trig for now then.

Cryptic Allusion Games / Cryptic Allusion, LLC
http://www.cagames.com/
Member
Posts: 153
Joined: 2004.12
Post: #15
Matrix math is just a convenient way of representing all of those trig equations in one neat little box

So learning the trig before matrices actually makes more sense... at least it did for me.

There was a long silence...
'I claim them all,' said the Savage at last.