07/01/2011 – By popular request updated to XNA 4.0, xna 3.1 code is still there too

One of the things I keep finding is people asking how to do a simple camera 2d in XNA. Today I decided to contribute with my own solution.

Most of the time the solution given is to have a class camera with a Vector2 position and when drawing the sprite batch to subtract the camera position to the sprite position itself. Although this work from my point of view it’s not elegant and you can’t have neat features like zooming and rotation. So for my tutorial I’ll do all transformations using a Matrix.
Start off by creating the basic class Camera2d

public class Camera2d
{
	protected float          _zoom; // Camera Zoom
	public Matrix             _transform; // Matrix Transform
	public Vector2          _pos; // Camera Position
	protected float         _rotation; // Camera Rotation

	public Camera2d()
	{
		_zoom = 1.0f;
		_rotation = 0.0f;
		_pos = Vector2.Zero;
	}
}

Now that we have the basic setup onto the variables it’s time to create a couple of functions to manipulate the variables

// Sets and gets zoom
public float Zoom
        {
            get { return _zoom; }
            set { _zoom = value; if (_zoom < 0.1f) _zoom = 0.1f; } // Negative zoom will flip image
        }
 
 public float Rotation
        {
            get {return _rotation; }
            set { _rotation = value; }
        }
 
        // Auxiliary function to move the camera
        public void Move(Vector2 amount)
        {
           _pos += amount;
        }
       // Get set position
        public Vector2 Pos
        {
             get{ return  _pos; }
             set{ _pos = value; }
        } 

And now for the function that calculates all the transformations

public Matrix get_transformation(GraphicsDevice graphicsDevice)
{
	_transform =       // Thanks to o KB o for this solution
	  Matrix.CreateTranslation(new Vector3(-_pos.X, -_pos.Y, 0)) *
								 Matrix.CreateRotationZ(Rotation) *
								 Matrix.CreateScale(new Vector3(Zoom, Zoom, 1)) *
								 Matrix.CreateTranslation(new Vector3(ViewportWidth * 0.5f, ViewportHeight * 0.5f, 0));
	return _transform;
}

So now how can we use it?

Simple on your sprite batch begin you must add the camera transformation.

Camera2d cam = new Camera2d();
cam.Pos = new Vector2(500.0f,200.0f);
// cam.Zoom = 2.0f // Example of Zoom in
// cam.Zoom = 0.5f // Example of Zoom out
 
//// if using XNA 3.1
spriteBatch.Begin(SpriteBlendMode.AlphaBlend,
                        SpriteSortMode.Immediate,
                        SaveStateMode.SaveState,
                        cam.get_transformation(device /*Send the variable that has your graphic device here*/));
 
//// if using XNA 4.0
spriteBatch.Begin(SpriteSortMode.BackToFront,
                        BlendState.AlphaBlend,
                        null,
                        null,
                        null,
                        null,
                        cam.get_transformation(device /*Send the variable that has your graphic device here*/));
 
// Draw Everything
// You can draw everything in their positions since the cam matrix has already done the maths for you 
 
spriteBatch.End(); // Call Sprite Batch End

Found any errors? Please let me know.