XNA camera for 2D games
This is just a quick article to share a nice way to create a camera for 2D games. There are a couple of ways to do this; I originally did it by making a class that held a position for the camera and then subtracting the object and camera positions when drawing to offset the sprites. This turned out to be a problem prone approach and caused me a few issues in my Imagine Cup game.
I recently noticed that it was possible to pass a transform matrix into the spriteBatch.Begin method which allows for a much nicer and more flexible approach to creating a cameras effect for a 2D game.
Below is the code for my Camera class that can be used for 2D games:
public class Camera { public Camera() { Position = Vector2.Zero; Zoom = 1f; } public Vector2 Position { get; set; } public float Rotation { get; set; } public float Zoom { get; set; } public Matrix TransformMatrix { get { return Matrix.CreateRotationZ(Rotation) * Matrix.CreateScale(Zoom) * Matrix.CreateTranslation(Position.X, Position.Y, 0); } } }
This code is all pretty simple so I’m not going to explain much. I would just like to highlight that for the rotation, we use the Matrix.CreateRotationZ function to create the camera rotation in 2D.
To use this class, all that needs to be done is create a new instance, perform your updates to the position, rotation and zoom then use the TransformMatrix property in the Begin method of your spriteBatch instance like so:
spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Texture, SaveStateMode.None, camera.TransformMatrix); spriteBatch.Draw(texture, Vector2.Zero, Color.White); spriteBatch.End();
And there it is! A nice camera solution for 2D games and it should also work for Windows Phone 7! And here is the source and XNA 3.1 demo project.
Related posts:
Categorised as: XNA
is there a way to get camera translation to stop once the end of the image is reached? I mean as to not show the blue background. I want to limit camera translation relative to the perimeter of the image.
otherwise great idea thank you very much! the way I was doing it was horrible!
When I first made a 2D camera, I calculated an offset position for every object which was horrible. This matrix transform approach is much nicer!
Restricting the movement of the camera is definately possible. The class in the article only defines the basic spatial data for the camera and handles the transformation calculation. It’s upto some other code to update the Position property (or you could modify the class).
If you know the dimensions of your game world and the size of the viewport then you can determine whether or not the camera should be allowed to move. You could update the camera class to accept an instance of the Rectangle class which represents the world bounds in the constructor. You could then add a method which is used for updating the camera position which would do the appropriate maths to restrict the movement.
If I get a bit of time I might try update the camera class to do this and then upload a sample project and link to it in this article.
To Expand on the world bounds and restricting camera ill say the following: (this is in theory, not taking the time to actually test)
in your Game.cs create a class level Rectangle and vars to store width/height
of your world
public class Game1: Micrsoft.Xna.FrameWork.Game
{
Rectangle worldBoundry;
int worldWidth;
int worldHeight;
//Then in your Initialize or LoadContent method of Game1 fill out vars and rectangle information
public void LoadContent()
{
worldWidth = 1000;
worldHeight = 1000;
worldBoundry = new Rectangle(0,0, worldWidth, worldHeight);
}
//Now that you have all that finish now for the method to restrict the cam //pos
public void CamRestrict()
{
if(cam.Position.X worldBoundry.width)
cam.Position.X = worldBoundry.width;
if(cam.Position.Y worldBoundry.height)
cam.Position.Y = worldBoundry.height;
}
// all you got to do is put the method in the Update() method.
// like i said Im not taking time to test but that should work
/. in theory.
wow ill do the cam restrict again, seems most of my stuff was cut out.
public void CamRestrict()
{
if(cam.Position.X worldBoundry.Width)
cam.Position.X = worldBoundry.Width;
if(cam.Position.Y worldBoundry.Height)
cam.Position.Y = worldBoundry.Height)
}
Ingore prev post’s method, it got all jacked up
}
ok done it again, but you should understand, if cam.x lessthan world bounds x cam x = world bounds x, samething with cam x greaterthan worldbounds width
cam x = worldbounds width. Do same for cam.Y,
Hi Richard,
Thanks for your comment(s). I’m not sure whats up with the WordPress and comments; it looks like it maybe has a length restriction and strips angled brackets to prevent HTML input.
Your example looks like it should basically work (I haven’t tried it). However I’m guessing that it might also show some of the background color defined in the GraphicsDevice.Clear method call. To prevent this I’d imagine you would need to take account for the games viewport dimensions so that the camera only ever moves to within exactly 1 frame width/height of the boundaries.