Friday, January 27, 2012

Game Elements 1: 2D Camera

Introduction

For my first tutorial I will explain how to create a 2D camera that follows a character using XNA. Since this is my first tutorial I will start a bit slow and introduce some basic concepts so that I do not have to spend as much time on them in future tutorials.

The reason I am making this and other tutorials is because I have been programming games for a few years and have made many beginner mistakes. In the case of Cameras I would often move keep the character stationary and then move the rest of the tiles, which worked fine initially but then I wanted to find the position of the player to see if they were standing on a button and I had to do a whole bunch of complex calculations. Then I learned this technique and my life became so much easier.

Displaying our Character and Background



Lets start with drawing our scene. I have included the two images I use above, you can also find them by following the link to the download package at the end of the tutorial.

First we need couple of local variables to the top of our Game1.cs file. Two for storing the images and two more for the characters position and speed:

// local variables used for this tutorial
Texture2D character, sandtile;
Vector2 position = new Vector2(100,100);
int speed = 5;


Next we load our images in the load content method as follows:

// load the two images
character = Content.Load("Images/character");
sandtile = Content.Load("Images/sand");

Then we draw our tiles using by repeatedly drawing the sand tiles in a loop, and then the character:

spriteBatch.Begin();

// Draw a 10 by 10 grid of tiles
for (int x = 0; x < 10; x++)
{
 for (int y = 0; y < 10; y++)
 {
  spriteBatch.Draw(sandtile, 
   new Vector2(x*sandtile.Width, y*sandtile.Height), null, Color.White, 0, 
   Vector2.Zero, 1, SpriteEffects.None, 0);
 }
}

// Draw the character using the position variable for its position
spriteBatch.Draw(character, position, null, Color.White, 0,
 new Vector2(character.Width / 2, character.Height / 2), 
 1, SpriteEffects.None, 0);

spriteBatch.End();
Moving the Character
Now that we have our scene lets get the character moving using the keyboard. Simply add this to the update method:
// Use arrow keys to move the player
if (Keyboard.GetState().IsKeyDown(Keys.Up))
{
 position.Y -= speed;
}
else if (Keyboard.GetState().IsKeyDown(Keys.Down))
{
 position.Y += speed;
}
if (Keyboard.GetState().IsKeyDown(Keys.Left))
{
 position.X -= speed;
}
else if (Keyboard.GetState().IsKeyDown(Keys.Right))
{
 position.X += speed;
}
If you run the game at this point, you will be able to move the character around. However, if you move to far in one direction you will disappear off the screen.
player can move, but camera does not follow
Creating the Camera
We will create the camera as a new class. It will have three variables for position, zoom and rotation and one function for obtaining the transformation matrix. We will make all of these static because generally in 2D games we will only use one camera. Here is the code for the camera class:
public class Camera
{
 public static Vector2 Position = Vector2.Zero;

 public static float Zoom = 1;

 public static float Rotation = 0;

 public static Matrix GetTransformation(GraphicsDevice graphicsdevice)
 {
  return Matrix.CreateTranslation(new Vector3(-Position.X, -Position.Y, 0)) *
   Matrix.CreateRotationZ(Rotation) *
   Matrix.CreateScale(new Vector3(Zoom, Zoom, 0)) *
   Matrix.CreateTranslation(new Vector3(
    graphicsdevice.Viewport.Width * 0.5f,
    graphicsdevice.Viewport.Height * 0.5f, 0));
 }
}
Once that is done we can apply the transformation to the spritebatch begin function in our games draw method:
// Notice that the last argument is the camera's transformation matrix.
// The other arguments are just the default values.
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, 
 SamplerState.LinearClamp, DepthStencilState.Default, 
 RasterizerState.CullCounterClockwise,
 null, Camera.GetTransformation(GraphicsDevice));
Lastly, add this to the end of the update method so that the camera position will be updated ever time the character position changes:
// when the player position changes, so should the camera
Camera.Position = position;
Now when you run the program you will notice that the character always stays at the center of the screen and the camera follows.
player stays at center of the screen and camera follows
Downloads
Source code and images can be found in the download package for this tutorial:
Extensions
I have covered the basics but there are a few more things you can do with this camera that you can try on your own. For example, try setting up keys for zooming and rotating the camera. You can also try to extend this so that the camera only moves when the character gets closer to the edge of the screen. Let me know in the comments below if you making something interesting or have any questions about this tutorial.

No comments:

Post a Comment