Beginners math-question on movement. (trigonometry)
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:
Depending on this, there are four ways to calculate the angles:
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.
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.
Reading through this yet another time, I see I've forgotten some things.
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.
- 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.
ThemsAllTook Wrote:This might help you: http://www.sacredsoftware.net/tutorials/...tors.xhtml
- 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.
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
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!
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.
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?
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?)
good luck with your project!
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?)
good luck with your project!
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?)
good luck with your project!
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..
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."
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.
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. )
Good point Best to stick with the trig for now then.
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.
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.
Possibly Related Threads...
Thread: | Author | Replies: | Views: | Last Post | |
For Beginners - article on game development | Byron Clarke | 0 | 2,917 |
Jan 19, 2006 03:23 PM Last Post: Byron Clarke |