Monday, December 5, 2016

xna - Simple thruster like behaviour when rotating sprite


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,



Answer



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.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...