Jump to content
  • Advertisement
Sign in to follow this  
VegaObscura

Move ship based on heading

This topic is 4139 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

I'm using directx9, and c++ to program a simple app. Basically I have a triangle which represents a ship (think asteroids) and I want to move it around the screen. As of right now I want my camera to stay directly in the center of the screen and always look in the same direction. Like all directx9 apps, it is in 3d space and I will move it on to being a 3d app where you fly around a room, but for now it is perfectly 2d as far as anyone can tell. Already I can move the ship up and down, side to side, and rotate it. The problem I'm facing right now is, when I press the up arrow the ship moves up, but instead of moving up I want it to move FORWARDS. That is, whatever direction the tip is facing. I'm sure you've all played asteroids before and my app is very similar to that right now. In asteroids you press left arrow to spin left, right arrow to spin right, up to accelerate and down to brake. That is exactly the controls I want to have. I use 2 global variables to determine where my ship should be. In the function that renders the frame every loop, it checks the keyboard to see if any of the arrow keys are pressed. If the up arrow is pressed, it moves the ship up by 0.05f, etc but I need to change that from moving up, to moving in whatever direction the ship is facing. Hopefully I haven't overexplained or underexplained.

Share this post


Link to post
Share on other sites
Advertisement
OK. The solution is a simple one but requires some trigonometry (which is also very simple if you ask me).
What you basically need is a heading vector.
But I need to ask u this: "Do you want it to slide (as in it can be headed in some way and moving in another) or do you want it to always move forwards?"

In both cases it is simple, but it would be confusing if you thought you are doing something and end up with something else.

Waiting your reply

Share this post


Link to post
Share on other sites
I've never done trigonometry before but if you say its simple I'm sure I will pick it up quickly. To answer your question, I do not want it to slide. I want it to always move directly towards its nose.

Share this post


Link to post
Share on other sites
Quote:
Original post by VegaObscura
I've never done trigonometry before but if you say its simple I'm sure I will pick it up quickly. To answer your question, I do not want it to slide. I want it to always move directly towards its nose.


I guess that your ship is represented using a position and an rotation angle. From that angle, you must find the heading vector (as arithma said).

Fortunately, it's not that complicated (but I really suggest you to learn some trigonometry AND some linear algebra (vector, matrices)).

Let U be the initial heading vector, and r be the rotation angle of your ship (r can be in degree or in radian; be aware that most math functions works with radian angles. Check your doc to see which unit you should use when calling them). The heading vector H is U rotated by r. Rotation is expressed using very basic trigonometry, but I'm pretty sure you'd like to avoid it [smile]

You can use D3DX functions to create the rotation matrix (D3DXMatrixRotation{X,Y,Z}, depending on the reference plane you are using), and then use D3DXVec2Transform() to apply the rotation to a 2D vector. You'll get a 4D vector whose x and y coordinates are H.


// assuming that you move on the X,Y plane
void find_final_heading(const D3DVECTOR2& initial_heading, float angle_in_radian, D3DVECTOR2& final_heading)
{
D3DMATRIX matrix_rot;
D3DVECTOR4 rot_result;

D3DXMatrixRotationZ(&matrix_rot, angle_in_radian);
D3DXVec2Transform(&rot_result, &initial_heading, &matrix_rot);

final_heading.x = rot_result.x;
final_heading.y = rot_result.y;
}


Once you have the final_heading vector, you update your position using:

// ship_x and ship_y are in/out variables
void update_position(const D3DXVECTOR2& heading, float speed, float& ship_x, float& ship_y)
{
x += heading.x * speed;
y += heading.y * speed;
}


HTH, (and hope that I'm not that wrong. I'm a bit rusty...)

Share this post


Link to post
Share on other sites
I don't use directx or opengl etc, but if there is some way of calling a directx function to rotate a vector then a simple explanation of what you need to do is...

Decide how fast you want your ship to move and set a vector so that the speed you have chosen is in the Y direction, and have the X direction at 0. Then just pass the vector to the rotation function using your ships heading as the rotation angle. The returned vector now contains the X and Y values you need to add to your ships current X and Y positions.

If you eventually want it to 'slide' so to speak or to have a gradual acceleration and deceleration instead of snap-moves then you start playing with adding the rotated vector to a velocity vector variable, which you then add to your position vector... but then you need to start considering if you want to cap the maximum velocity of your ship, which is do-able but requires another step or two.

This can all then be applied in 3D if you get that far, but again it requires some more steps and gets a bit more complicated. Bit by bit you get to where you want to go... it just takes one step at a time.

(and there you have it. beaten by 3 minutes)

Share this post


Link to post
Share on other sites
Quote:
Original post by VegaObscura
I've never done trigonometry before but if you say its simple I'm sure I will pick it up quickly. To answer your question, I do not want it to slide. I want it to always move directly towards its nose.


U have a variable called heading (in radians) that defines the angle between the x-axis and the forward vector of your ship.

OK... You need some magic! to convert that heading into a vector. Let's say the vector is called u.
u.x = cos(heading)
u.y = sin(heading)
That's all the trig you'll need

Let's say you have a speed variable too somewhere and a position vector p defined somewhere.
Then you'd update your position based on the simple equation:
p += dt * u * speed;
where dt is your time delta (amount of time in current frame or something like that), u is your calculated direction vector.

Things you should notice: This is not the physically correct way to do things..
I once preferred it over the sliding method but it made my collision responses a living hell. Implement it for learning purposes then switch into more physically correct methods.

GD Community will prove supportive :)

Share this post


Link to post
Share on other sites
Quote:
Original post by Emmanuel Deloget
(D3DXMatrixRotation{X,Y,Z}, depending on the reference plane you are using), and then use D3DXVec2Transform() to apply the rotation to a 2D vector. You'll get a 4D vector whose x and y coordinates are H.


Note that D3DXMatrixRotationZ works in clockwise rather than the mathematical convention of counter clockwise...

Share this post


Link to post
Share on other sites
The easy / high-performance / Atari 2600-style way to do this is:
1. Decide how many different angles you want to point. As I recall, Atari games let you point in a total of 16 directions (N, NNE, NE, ENE, etc.), and this is sufficient.
2. Calculate sin and cos for those angles and apply them as recommended by other posters. Hard-code those values into your program.
3. With just a little cleverness, you can represent only 3 diagonals and "rotate" them for the other 9 diagonals.

This implementation is useful if you ever use SDL for graphics, where you don't have hardware-accelerated rotation available (that I know of). But then again, I guess DX9 can do fast rotations... so nevermind anything I just said.

Share this post


Link to post
Share on other sites
2 questions, the first simple one, what kind of variable should I use to store radians? The second, much bigger one, what is a vector?

Share this post


Link to post
Share on other sites
Quote:
Original post by VegaObscura
2 questions, the first simple one, what kind of variable should I use to store radians? The second, much bigger one, what is a vector?


Guess you should begin by reading this, as well as many other math tutorial. It's really going to help you a lot.

Share this post


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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!