# XNA Camera 2d with zoom and rotation

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.

### How To Speed Up Firefox 3

• Koja says:

Hi, I think that I solved the problem with camera delay. I just added this line: graphics.PreferMultiSampling = true; and camera is working fine in full screen too. Thanks for this awesome tutorial!

• Umair says:

Hi David,

Thanks a lot for the tutorial. I have a question regarding zooming at a specific spot and camera size.

I am making an RTS and I want the camera to zoom at the point on the screen where the cursor is. I am using a touch interface of windows phone, so I want the camera to zoom at the point where the user has put his fingers and performed the pinch gesture.

In other words, I want the center of the camera to shift to the point where the zoom is being performed.

Another problem is that, I have limited the camera in a rectangle. It works well as long as I am zoomed out and drag the camera around. Say that I drag and reach the top-right corner in the zoomed out state. now when I zoom in, I can no longer see what is present at the top right corner as the camera size remains the same, but it has zoomed in to the center.

I gather that I will need to change the size of the camera as I zoom in. How can this best be done?

• Steve says:

Great code, saved me ages and opened up lots of possabilities. Thanks. But I’ve had a problem where if at ANY time I switch rendertarget, then return to the default rendertarget, either in a component, class or in the main loop the screen goes purple. I’ve only had this problem when using the camera and cant figure it out. Any idea?

• Steve says:

Forget my previous post, I was switching renderTarget in the Draw call, I’m now doing it in the update loop, creating the texture and then drawing the result it in the draw call. it’s now working as I’d intended. Thanks again though for the great blog!

• Great post, helped me figure out the glitch in the code I was using (it was calculating the middle of the screen after transformations were performed, creating a ghost image whenever I zoomed in for one frame)

• Mo says:

hey,
thank you for the tutorial (=
but I have a question:
I use a Leveleditor to create the game-levels.
You can choose “blocks” and you can set them somewhere in the editor. Then you save this file and open it while playing the current level in game.
The problem: When you want to zoom / rotate the “blocks” the level starts “flashing” – so there are white lines that are blinking the whole time while you are zooming (on the border of every tile-block)
In an other forum I asked for this and sb. told me to render the level or I should try to create “overlapping tiles” (so that the tiles overlap each other). I tried that but It doesn´t work…
do you know what the problem is.. because I don´t know how to render my level- so maybe there is an other way to solve the problem?!
thank you (=

• lolxdfly says:

i am just learning c#/xna!

There is an error:
The name “ViewportWidth” in the current context does not exist.
The name “ViewportHeight” in the current context does not exist.

• Alex says:

I noticed that the coordinate system doesn’t change when you zoom in the camera.
I made a tweak and now works: in the function “get_transformation”, change:
“new Vector3(-_pos.X, -_pos.Y, 0))”
in “new Vector3(-_pos.X * Zoom, -_pos.Y * Zoom, 0))”
(notice the *Zoom). You may want to change the code in the example.

• @lolxdfly
public Matrix get_transformation(GraphicsDevice graphicsDevice)
{
Viewport viewPort= graphicsDevice.Viewport;
// Name of Graphics device, from the function get_

// rename the ViewportWidth to call the new viewPort.Width; we just added.
Matrix.CreateTranslation(new Vector3(viewPort.Width * 0.5f, viewPort.Height * 0.5f, 0));

Alternatively you do something like
var ViewportWidth = graphicsDevice.Viewport.Width;

• nelz says:

Hi can u explain what is this graphic device? in you parameter ing cam.get_transformation? Sorry im just a noooobie in xna

• Janus says:

This is awesomely simple and well explained. Thank you!

• apophis117 says:

Excellent! It works!
I just need the zoom to zoom in on the centre instead of the top-left.

Thank you, David.

• xnaGuy says:

Hi David,

Thanks for the great tutorial, you really helped out with my project!

I see in your video that the bottom left text does not zoom with the rest of the game. Could you please show how this can be done? So far I can make the text move next to the camera, but if the Camera.Zoom 1.0f then the text is out of place.

• goshohib says:

it’s very useful. thanks alot sir

• Rob says:

Thank you so so so so mcuh!

• I’m learning XNA by creating my own RPG game from scratch and thought that I was “too far” into the process to add camera stuff, thinking I’d need to rewrite a bunch of code. But nope, this tutorial was incredibly simple and straightforward, and I only needed to change one line after writing up a camera class.

Thanks for posting this, it certainly demystified a bunch of XNA stuff for me!

• Thanks Works good, i solve my problem of resolution of 1920×1080 whit the zoom. Great!!

• so I am getting Null Reference Exception on the draw, any idea why/how to fix?

• thái says:

thank very much