• Advertisement
Sign in to follow this  

2D Motion and Vectors

This topic is 4213 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi All, I am really having a difficult time learning about motion in 2D (or 3D for that matter). I found a great site that had a 2D Vector Class to use, but my problem is that I don't understand how to use it. I understand that I would need my object (a car for example) to have a vector for its current location, it would also need a velocity variable with an angle and magnitude to calculate the next point where the car will end up. I don't quite understand how to incorporate velocity and angles into the mix. I am not really a great mathematician so this is really hard for me to understand. Can someone point me in the right direction on how to work with vectors, angles and motion (doesn't even have to be related to programming). I want to make a small car game, but my lack of maths skills is really holding me back. Any help is greatly appreciated Thanks

Share this post


Link to post
Share on other sites
Advertisement
I think you'll need to look into Sine and Cosine, for angular movement. If you're using C++, you can include math.h for sin() and cos(). For example, to move at an angle(in degrees) at your current speed, you would do this:
x+=cos(degrees_to_radians(angle))*speed;
y-=sin(degrees_to_radians(angle))*speed;

Degrees_to_radians would be something like this(C++):
float degrees_to_radians(float number){
return number/(180/M_PI);
}

If you'd like to understand HOW these work, you could look up some trigonometry lessons on google or something.

Share this post


Link to post
Share on other sites
Thanks dude, that was really helpfull. I will try it out tonight although I am not sure if the results of those equations will map to the screen coordinate system. I might have to look into so trig stuff on the net. Thanks again.

Share this post


Link to post
Share on other sites
You're welcome :D

If you're worried about it working with the screen coords, I wrote that assuming 0,0 was in the top-left corner of your screen. If it's in the bottom-left, then just change the "y-=stuff" to "y+=stuff". Good luck with your game!

Share this post


Link to post
Share on other sites
I will plug your code into my game so far and see how it goes. Its basically just me moving a square around the screen as though it was a Car. Its all SDL based. Just sort of starting off.

Thanks again. I will update on how it goes.

Share this post


Link to post
Share on other sites
Hi again,

I put that code into my game and it works... sort of. I think it might be in my implamentation.

Here is my car object (with some stuff removed for brevity)


class Car
{
private:
SDL_Surface* m_Sprite
int x,y; // Coo-ords (x,y)
int direction,speed; // Direction = angle 0-359 **Is that right?**
public:
//...
void Accelerate() { speed = speed + 1; };
void Decelerate() { speed = speed - 1; };

void TurnLeft()
{
direction = direction - 1;
if(direction < 0) direction = 359;
}

void TurnRight()
{
direction = direction + 1;
if(direction > 359) direction = 0;
}
void Update()
{
x += cos(degrees_to_rad(direction))*speed;
//...
// Check Leave Screen here & adjust
//...
y += sin(degrees_to_rad(direction))*speed;
//...
// Check Leave Screen here & adjust
//...
}
};




The direction can be any value between 0 and 359. Perhaps this is the point that is going wrong. I am not too sure. I currently only have the code compiled on Linux, but I can probably make a windows executable if you want to look at it (unless you are on Linux to begin with).

Thanks so much for the help so far. It feel really good to have it working, even if it is behaving improperly.

[Edited by - timbobsteve on August 11, 2006 2:45:49 AM]

Share this post


Link to post
Share on other sites
Your treatment of sin and cos is ok, assuming that (a) you understand your coordinate system (In mathematics, we let an angle of 0 be to the right, and increasing value turns counter-clockwise; however, in math we draw positive y going up, but most screen-position APIs treat positive y as going downwards, so you sometimes have to use -sin where you'd expect to use sin, or do the mapping elsewhere), and (b) your degrees_to_rad() function works.

The bug here is that in Update(), because the direction and speed represent *velocity* of the car, but x and y represent *position*, you want to *add* the cos/sin components to the x and y, rather than setting them.

That said:

- You need a semicolon after the m_Sprite declaration (since you have something compiling, I assume that's just a typo in shortening things for board posting).

- You can use the 'immediate' mathematical operators in order to avoid typing redundant things. It's also more expressive: in real life, you wouldn't command "set x to be x plus 1", but instead "add 1 to x". In C++, this translates as "x += 1". Similarly, there exist -=, *=, /=, and most if not all other combinations you would expect (I don't know what you'd expect ;) ).

For the special case of adding or subtracting 1, you can also use "x++" or "++x", but I usually (teach to) use these only in specific circumstances where it's idiomatic C++ to do so.

- To make values "loop around", you can try making use of the modulus (%) operator. It returns the remainder of a division.

- Some real-world APIs use, instead of degrees, "256ths of a circle". That way, you don't have to write any looping around explicitly: you store the value in a signed char, and the overflow behaviour takes care of things automatically (if the value hits 256, the 256-bit is discarded since it overflows the type, and you get 0 again). This is not terribly intuitive, though, and smells of premature optimization - but it's worth exposure to different techniques so you can get an idea of how these things work.

- By the way, good job with your class design so far, from what I can see. You have abstracted things properly and made functions that do real work; a concept that ought to be obvious, but with which many people inexplicably have huge amounts of trouble. With abstractions like 'accelerate()', you have a convenient place to add code as you develop your "physics model" to make the car behaviour more accurate.

Share this post


Link to post
Share on other sites
Thanks for the reply Zahlman. I think you are right when you talk about my current implimentation of the coordinate system.

I will try some of the stuff you said. I know what you mean about making code shorter (like using ++x instead of x = x + 1), but you will find that these forums don't display "++x" properley, instead of:

"++x"

it displays

" x" (no pluses)

Its only when you put it in the "{source}" brackets for formating that it doesn't display. That is the only reason why I took the time to type it all out. I will mostly take the shorter option ( "++" or "+=" etc ) if possible.

I will try playing with the coordinates system and how I change the value of x and y. I will get back to you later.

Thanks again.

Share this post


Link to post
Share on other sites
Quote:
Original post by timbobsteve
Thanks for the reply Zahlman. I think you are right when you talk about my current implimentation of the coordinate system.

I will try some of the stuff you said. I know what you mean about making code shorter (like using ++x instead of x = x + 1), but you will find that these forums don't display "++x" properley, instead of:

"++x"

it displays

" x" (no pluses)



++worksforme;

Share this post


Link to post
Share on other sites
For some wicked reason, the preview doesn't show plus symbols. They will, however, be visible in the actual reply when you submit it.

Share this post


Link to post
Share on other sites
This may be a bit more simplistic than it should be but a presentation program I've been working on requires a straight line movement from point A to point B. I allow for the intermediate x and y co-ordinates to be determined independently. What I currently pass to the function that determines its rate of movement is how many cycles it takes to get from point A to point B.

From memory and sort of pidgin coding C:



void Object::SetUpMove (rect A, rect B, unsigned int cycles)
{
xSlope = (float)(B.x - A.x)/(float) cycles;
ySlope = (float)(B.y - A.y)/(float) cycles;
origx = A.x; origy = A.y;
NumCycles = 0; // start counter at zero
MaxCyles = cycles;
}



xSlope and ySlope are member floats of the class as MaxCycles and NumCycles are unsigned int members. I probably set a flag in there specifying that there an active animatiion/move going on.

On each pass to update, I'm assuming that some sort of timing control is goin on I call a function I called Click() against all objects that tells them to check for active animation/moves/whatevers and to do what the object is supposed to do.



bool Object::Click()
{
if (!action) return false;
// checks for other actions
// if it shows a linear move......

xpos = origx + (int)(xSlope * NumCycle);
ypos = origy + (int)(ySlope * NumCycle);
NumCycle++;
}



This approach relieved me of trying to base the y position on the x position for each cycle and eliminated the trig functions.

The directive to draw the object on the screen comes after all objects have been updated.

As I say, a bit simplistic but it works for my purposes. When it comes to actually doing more precise timing on it I'd likely work out a means of determining 'cycle' to be based on the tic count since starting divided by the total number of tics it should take to get to point B.

Share this post


Link to post
Share on other sites

So the topics covered here are basically what allow for the creation of Street Fighter, FInal Fantasy 6, and Chrono Trigger/Xenogears?

Share this post


Link to post
Share on other sites
OK. I got it all to work. It turns out the eratic response was due to the angle(direction) being increased too quickly (e.g. direction + 2 intead of +1) also the speed was a bit too high also.

Thanks for everyone that took the time to reply and help out. For those who want to know what worked for me


// Declare PI to whatever value you use for pi
const int PI = 3.1415

// You need to write the degrees2radians function
void degrees2radians(float angle)
{
return number/(180/PI);
}

// Do this in the update for your object
new_xPosition += cos( degrees2radians( direction ) ) * speed;
new_yPosition += sin( degrees2radians( direction ) ) * speed;




Thanks again everyone. No doubt my quest will raise other questions so I may see you all soon :P

EDIT: My objects were moving quite strangely e.g. object velocity = (1,0) at an angle of 45 degrees and speed of 1 unit when it should be (1,1).

This was my own fault. I was holding the positions of each object in a struct like the following:

struct Vector
{
int x,y;
}



The problem was that the integer values didn't hold onto the decimal values (obviously) and my movement speed would have to be greater than 1 to get proper velocity values.

Thankyou again to everyone that helped. I now am well on my way to understanding basic movement and trig. :D Hooray!

[Edited by - timbobsteve on August 13, 2006 11:54:05 PM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement