XNA Level 2 Lesson 2
Translation and Rotation
- Adding Key Control
- Time Based Movement
- Translation Maths
|
|
|
In our last game we simply used the keys to add values to the X and Y coordinates (Position) to move out sprite up, down and across the screen. That is all well and good unless we want to move at a specific angle.
To do that we simply need a bit of trigonometry :)
We take the current position and multiply the velocity by the Cos and Sin of the anlgle, it looks something like this.
X += Velocity * Cos(angle)
Y += Velocity * SIn(angle)
So let’s say your tank was currently 100 pixels across and 100 pixels down, traveling at 10 pixels per frame at an angle of 15 degrees
New X = 100 + (10 * Cos(15))
New Y = 100 + (10 * Sin(15))
New X = 109.65
New Y = 102.58
Adding Key Control and Time based Movement
Go to the Update Function and add the following code. It is practically the same except for one new line, the new elapsed variable. Elapsed is the calculation of how much time has passed since the last time the update function was called.
This will allow us to move our sprite based on the amount of time between frames
KeyboardState key = Keyboard.GetState();
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
if (key.IsKeyDown(Keys.Left))
{
}
if (key.IsKeyDown(Keys.Right))
{
}
if (key.IsKeyDown(Keys.Up))
{
}
if (key.IsKeyDown(Keys.Down))
{
}
Rotation
Simply update the rotation value when pressing Left and Right
if (key.IsKeyDown(Keys.Left))
{
rotation -= 1.0f * elapsed;
}
if (key.IsKeyDown(Keys.Right))
{
rotation += 1.0f * elapsed;
}
Press F5, you should now be able to rotate the tank using the arrow keys
Translation
Now we have a rotation angle, we can use the formula
X += Velocity * Cos(angle)
Y += Velocity * SIn(angle)
to move our tank the direction it is heading.
Important
Computers will nearly always use ‘Radians’ not ‘Degrees’
As I am sure you are aware there are 360 degrees in a circle
There are 2pi radians in a circle (approximately 6.284 radians)
Don’t worry too much about this, it simply means if you are trying to move along a heading of 180 degrees, you actually need to go along a heading of approximately 3.142
So if you entered 180 when it expected radians, it would in fact be 565 degrees!!!
Add the following code to your Keyboard Up command, please note that I like to create temporary X and Y variables and the add them to the position.
if (key.IsKeyDown(Keys.Up))
{
float x, y;
x = (100 * elapsed) * (float)Math.Cos(rotation);
y = (100 * elapsed) * (float)Math.Sin(rotation);
position.X += x;
position.Y += y;
}
Can you make your tank reverse?
Completed Listings
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
//Global Variables
protected Texture2D SpriteSheet;
protected Vector2 position;
protected float rotation;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
position = new Vector2();
rotation = 0;
position.X = 200;
position.Y = 200;
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
SpriteSheet = Content.Load<Texture2D>("TankSpriteSheet");
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
KeyboardState key = Keyboard.GetState();
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
if (key.IsKeyDown(Keys.Left))
{
rotation -= 1.0f * elapsed;
}
if (key.IsKeyDown(Keys.Right))
{
rotation += 1.0f * elapsed;
}
if (key.IsKeyDown(Keys.Up))
{
float x, y;
x = (100 * elapsed) * (float)Math.Cos(rotation);
y = (100 * elapsed) * (float)Math.Sin(rotation);
position.X += x;
position.Y += y;
}
if (key.IsKeyDown(Keys.Down))
{
float x, y;
x = (-100 * elapsed) * (float)Math.Cos(rotation);
y = (-100 * elapsed) * (float)Math.Sin(rotation);
position.X += x;
position.Y += y;
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.SeaGreen);
spriteBatch.Begin();
spriteBatch.Draw(SpriteSheet, position, new Rectangle(0, 0, 128, 128),
Color.White, rotation, new Vector2(64, 64), 1.0f, SpriteEffects.None, 1);
spriteBatch.End();
base.Draw(gameTime);
}
|