Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm prototyping some 2D game concepts with XNA and have added some basic keyboard inputs to control a triangle sprite.

When I press key up the sprite accelerates in it's current facing direction, when I release the key it brakes down.

For rotation, when I press left/right keys I rotate the sprite.

Currently the sprite immedately changes direction when I rotate it. What I want is for it to keep moving in the same direction when I rotate, until I hit key up, adding thrust in whatever direction the sprite is pointing at.

This would simulate thrusters on a classic space shooter like Asteroids.

I'm adding an image to describe the behaviour I'm after and some code samples of how I'm doing things at the moment.

ship path

This is my player struct, holding information of the sprite.

    public struct PlayerData
    {
        public Vector2 Position;  // where to draw the sprite
        public Vector2 Direction; // travel direction of sprite

        public float Angle;       // rotation of sprite

        public float Velocity;
        public float Acceleration;
        public float Decelleration;
        public float RotationAcceleration;
        public float RotationDecceleration;

        public float TopSpeed;
        public float Scale;
    }

This is how I'm currently handling thrusting / braking (when pressing/releasing key up) (simplified, removed some bounds checking etc):

player.Velocity += player.Acceleration * 0.1f;
player.Velocity -= player.Acceleration * 0.1f;

And when I rotate the sprite left and right:

player.Angle -= player.RotationAcceleration * 0.1f;
player.Angle += player.RotationAcceleration * 0.1f;

This runs in the update loop, keeps the direction updated and updates the position:

Vector2 up = new Vector2(0f, -1f);
Matrix rotMatrix = Matrix.CreateRotationZ(player.Angle);
player.Direction = Vector2.Transform(up, rotMatrix);

player.Direction *= player.Velocity;

player.Position += player.Direction;

I am following along various beginner tutorials and haven't found any describing this, but I have tried some on my own without success. Do I need to change my velocity and acceleration fields to Vectors instead of floats to accomplish this type of movement? I realise my Angle and the Direction vector is currently tied together and I need to disconnect these somehow to be able to rotate freely without changing the direction of the movement, but I can't quite figure out how to do this while keeping the acceleration/decceleration functional.

Would appreciate an explanation rather than pure code samples.

Thanks,

share|improve this question
    
why don't you just add the rotation to the velocity vector, and then normalize, and multiply by the speed –  gardian06 Apr 1 '12 at 21:41
add comment

2 Answers

up vote 4 down vote accepted

You're actually very close to the behavior you want. You just need to decouple the direction the player is facing and the direction he's moving.

The only value the angle of the player should affect is the thruster force. Each frame, you'll calculate the total acceleration vector of the player as the sum of the forces that are acting upon him, in this case, just your thruster:

Vector2 up = new Vector2(0f, -1f);
Matrix rotMatrix = Matrix.CreateRotationZ(player.Angle);
Vector2 thrusterForce = Vector2.Transform(up, rotMatrix) * thrusterPower;

player.Acceleration = thrusterForce;

Then you can apply the acceleration to the player's velocity:

player.Velocity += player.Acceleration * deltaTime * deltaTime;

Notice that the acceleration is multiplied by deltaTime (the amount of time that elapsed since the last frame) twice. This is because the units of acceleration are meters per second squared (assuming meters are your unit of length).

Finally you can move the player by the velocity:

player.Position += player.Velocity * deltaTime;

What's important here is that the direction the player is moving is always the direction of the player's velocity, and not the angle the player is facing. The velocity will change over time when the thruster is being used, giving the player the sliding behavior reminiscent of Asteroids that you're looking for.

share|improve this answer
    
Excellent description, got it to work. Thanks. –  ensamgud Apr 3 '12 at 19:44
add comment

Something very simple like this should work :

//some constants
const float rotation_vel = ...;
const float thrust = ...;

if(keyup)
{
   player.velocity.x += cos(player.angle) * thrust;
   player.velocity.y += sin(player.angle) * thrust;
}

if(keyleft)
{
   player.angle -= rotation_vel;
}

if(keyright)
{
   player.angle += rotation_vel;
}

player.position += player.velocity;

//draw player sprite at position player.position and with angle player.angle
...
share|improve this answer
    
you should normalize player.direction after adding it to the player.position –  Blau Apr 1 '12 at 23:44
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.