Public Group

# Move ship based on heading

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

## 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 on other sites
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.

##### 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 on other sites
Quote:
 Original post by VegaObscuraI'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 planevoid 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;  }

// ship_x and ship_y are in/out variablesvoid 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 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 on other sites
Quote:
 Original post by VegaObscuraI'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.
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 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 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 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 on other sites
Quote:
 Original post by VegaObscura2 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.

1. 1
Rutin
37
2. 2
3. 3
4. 4
5. 5

• 12
• 10
• 13
• 104
• 11
• ### Forum Statistics

• Total Topics
632983
• Total Posts
3009697
• ### Who's Online (See full list)

There are no registered users currently online

×