# Overview

A camera can be an essential part of your game when you need to create game worlds that expand beyond the scope of the game windows width and height. The concept of a camera can seem overwhelming at first, but here we'll layout the groundwork as simple as possible in a way that you can expand on to suite your game project's needs.

Creating a camera will require the use of vectors math and matrices math to create a Transformation Matrix. It is beyond the scope of these tutorials to explain the math behind it. If you would like to further research this topic, the article The Transform Matrix For 2D Games is a good starting place.

# Project Files

If you would like to follow along with this tutorial using the same files and assets I use, you can find them here on github.

## Create the Camera Class

If you are unfamiliar with the concept of a camera in game development, it is gives us something called a Transformation Matrix, which we can then apply to our rendering. This transformation matrix contains the information to translate, rotate, and scale what we tell to render so that it looks as if we're viewing the game from the perspective of the camera.

To get started, create a new class for your camera, I'll call mine `Camera2D`

. Add the following:

```
public class Camera2D
{
// The transformation matrix of the camera
private Matrix _transformationMatrix = Matrix.Identity;
// The inverse of the transformation matrix
private Matrix _inverseMatrix = Matrix.Identity;
// The xy-coordinate top-left position of the camera
private Vector2 _position = Vector2.Zero;
// The rotation of the camera along the Z axis
private float _rotation = 0;
// The x and y zoom level of the camera
private Vector2 _zoom = Vector2.One;
// The xy-coordinate origin point of the camera
private Vector2 _origin = Vector2.Zero;
// Has the position, angle, origin, or zoom of the camera changed
private bool _hasChanged;
// The Viewport reference for the camera
public Viewport Viewport;
/// <summary>
/// Creates a new 2D camera instance
/// </summary>
/// <param name="viewPort">The Viewport reference for the camera</param>
public Camera2D(Viewport viewPort)
{
Viewport = viewPort;
}
/// <summary>
/// Creates a new 2D camera instance
/// </summary>
/// <param name="width">The width of the viewport</param>
/// <param name="height">The height of the viewport</param>
public Camera2D(int width, int height)
{
Viewport = new Viewport();
Viewport.Width = width;
Viewport.Height = height;
}
}
```

Below is an explanation the fields we've added above to further clarify their purpose for our camera.

Field | Type | Description |
---|---|---|

`_transformationMatrix` |
Matrix | This is the matrix that we will calculate in a minute that includes our translation, rotation, and scale information. This will be used by the `SpriteBatch` when we perform our rendering. |

`_inverseMatrix` |
Matrix | This is the inverse of our transformation matrix. |

`_position` |
Vector2 | This is the xy-coordinate position of our camera relative to the top-left of the camera's view. In terms of our transformation matrix, this is the translation/ |

`_rotation` |
float | This is the angle of rotation for our camera. In terms of our transformation matrix, this is the rotation. |

`_zoom` |
Vector2 | This is the zoom level of the camera. In terms of our transformation matrix, this is the scale. |

`_origin` |
Vector2 | This is the origin point of our camera. By default, it is Vector2.Zero, which means our camera's origin is the top-left. |

`_hasChanged` |
bool | This is a boolean value we'll set to true anytime either the position, rotation, or scale of the camera has changed, signifying that we need to update our transformation matrix. |

`ViewPort` |
ViewPort | This is the Viewport reference for our camera. |

After the fields are declared, two constructors are introduced. The first constructor allows us to pass in a reference to an existing `ViewPort`

. This is useful because it allows us to use the Viewport from our Game1 class provided by default by MonoGame. The second constructor allows use to supply a width and height, which will create a viewport reference for use base on these dimensions.

## Updating the Matrices

To keep our transformation matrix and inverse matrix updated, we'll create a method called `UpdateMatrices`

. Calculating a new transformation matrix is done through the multiplication of a translation matrix of our `_position`

, a rotation matrix of our `_rotation`

, a scale matrix of our `_zoom`

, and an additional translation matrix of our `_origin`

. Once we have each of these individual matrices, we can multiply them all together to get our final `_transformationMatrix`

. Then to get the value of our `_inverseMatrix`

, we just inverse the transformation matrix.

Add the following method to our Camera2D class

```
/// <summary>
/// Updates the values for our transformation matrix and
/// the inverse matrix.
/// </summary>
private void UpdateMatrices()
{
// Create a translation matrix based on the position of the camera
var positionTranslationMatrix = Matrix.CreateTranslation(new Vector3()
{
X = -(int)Math.Floor(_position.X),
Y = -(int)Math.Floor(_position.Y),
Z = 0
});
// Create a rotation matrix around the Z axis
var rotationMatrix = Matrix.CreateRotationZ(_rotation);
// Create a scale matrix based on the zoom
var scaleMatrix = Matrix.CreateScale(new Vector3()
{
X = _zoom.X,
Y = _zoom.Y,
Z = 1
});
// Create a translation matrix based on the origin position of the camera
var originTranslationMatrix = Matrix.CreateTranslation(new Vector3()
{
X = (int)Math.Floor(_origin.X),
Y = (int)Math.Floor(_origin.Y),
Z = 0
});
// Perform matrix multiplication of all of the above to create our
// transformation matrix
_transformationMatrix = positionTranslationMatrix * rotationMatrix * scaleMatrix * originTranslationMatrix;
// Get our inverse matrix of the transformation matrix
_inverseMatrix = Matrix.Invert(_transformationMatrix);
// Since the matrices have now been updated, set that there is no longer a change
_hasChanged = false;
}
```

And that's it for the hard stuff. This will keep the transformation and inverse matrix values updated whenever there is a change to the position, rotation, or scale. Next, we'll create the public properties that can be used to retrieve the values needed from the camera to use within the game.

## Adding Camera Properties

The first two properties that we are going to add are for the TransformationMatrix and the InverseMatrix. Add the following to the Camera2D class.

```
/// <summary>
/// Gets the cameras transformation matrix
/// </summary>
public Matrix TransformationMatrix
{
get
{
// If a change is detected, update matrices before
// returning value
if(_hasChanged)
{
UpdateMatrices();
}
return _transformationMatrix;
}
}
/// <summary>
/// Gets the inverse of the camera's transformation matrix
/// </summary>
public Matrix InverseMatrix
{
get
{
// If a change is detected, update matrices before
// returning value
if (_hasChanged)
{
UpdateMatrices();
}
return _inverseMatrix;
}
}
```

Both of these just return their respective backing fields, however, before returning, they check if the `_hasChanged`

boolean is true. If it is, a call to update our matrices is performed first before returning the values. Next we'll add a few additional properties that will allow the adjustment of the camera's position, rotation, scale, and origin. Add the following to the Camera2D class:

```
/// <summary>
/// Gets or Sets the xy-coordinate position of the camera relative
/// to the world space of the game
/// </summary>
public Vector2 Position
{
get { return _position; }
set
{
// If the value hasn't actually changed, just return back
if (_position == value) { return; }
// Set the position value
_position = value;
// Flag that a change has been made
_hasChanged = true;
}
}
/// <summary>
/// Gets or Sets the rotation angle of the camera
/// </summary>
public float Rotation
{
get { return _rotation; }
set
{
// If the value hasn't actually changed, just return back
if (_rotation == value) { return; }
// Set the rotation value
_rotation = value;
// Flag that a change has been made
_hasChanged = true;
}
}
/// <summary>
/// Gets or Sets the zoom level of the camera
/// </summary>
public Vector2 Zoom
{
get { return _zoom; }
set
{
// If the value hasn't actually changed, just return back
if (_zoom == value) { return; }
// Set the zoom value
_zoom = value;
// Flag that a change has been made
_hasChanged = true;
}
}
/// <summary>
/// Gets or Sets the origin point of the camera relative to the
/// ViewPort
/// </summary>
public Vector2 Origin
{
get { return _origin; }
set
{
// If the value hasn't actually changed, just return back
if (_origin == value) { return; }
// Set the origin value
_origin = value;
// Flag that a change has been made
_hasChanged = true;
}
}
/// <summary>
/// Gets or Sets the camera's x-coordinate position relative to the world
/// space of the game
/// </summary>
public float X
{
get { return _position.X; }
set
{
// If the value hasn't actually changed, just return back
if (_position.X == value) { return; }
// Set the position x value
_position.X = value;
// Flag that a change has been made
_hasChanged = true;
}
}
/// <summary>
/// Gets or Sets the camera's y-coordinate position relative to the world
/// space of the game
/// </summary>
public float Y
{
get { return _position.Y; }
set
{
// If the value hasn't actually changed, just return back
if (_position.Y == value) { return; }
// Set the position y value
_position.Y = value;
// Flag that a change has been made
_hasChanged = true;
}
}
```

The getter for each of these properties return back their respective backing field values. In each of the setters, first a check to see if the value has actually changed is performed. If it is actually a new value, the value is set to the respective backing field, and the `_hasChanged`

boolean is set to true, indicating that a change has been made. The last two properties `X`

and `Y`

are mostly there for utility so we can set them individually instead of having to supply a full Vector2 each time to `Position`

.

That's it for our properties.

## Screen Space to Camera Space Methods

By introducing a camera into our game, we've also created two separate coordinate spaces.

System | Definition |
---|---|

World Space |
The World Space coordinate system defines the xy-coordinate location of the entities within our game's world. |

Screen Space |
The screen space coordinate system defines the xy-coordinate location relative to the game's window, with the top-left of the game window being xy-positiong {0, 0}. This is the coordinate system things outside of our game, such as the players mouse, exist in. |

To further expand on this concept, take a look at the following image:

On the left is our game world. The game world is 2000px wide by 2000px tall. In this game world, our player is located at world space xy-position {1000, 900}. On the right is our game screen that is being rendered. The game screen is only 1280px wide by 720px tall. We have the mouse at screen space xy-position {1000, 650}.

We need something that is going to translate between these two coordinate systems. Thankfully, it's actually not too difficult. In our Camera2D class, add the following two methods

```
/// <summary>
/// Translate the given screen space xy-coordinate position
/// to the equivalent world space xy-coordinate position
/// </summary>
/// <param name="position">The xy-coordinate position in screen space to translate</param>
/// <returns>
/// The xy-coodinate position in world space
/// </returns>
public Vector2 ScreenToWorld(Vector2 position)
{
return Vector2.Transform(position, InverseMatrix);
}
/// <summary>
/// Translates the given world space xy-coordinate position
/// to the equivalent screen space xy-coordinate position
/// </summary>
/// <param name="position">The xy-coordinate position in world space to translate</param>
/// <returns>
/// The xy-coordinate position in screen space
/// </returns>
public Vector2 WorldToScreen(Vector2 position)
{
return Vector2.Transform(position, TransformationMatrix);
}
```

With these two methods, we can translate between the two coordinate systems.

## Using the Camera

To use our camera in our game, first we need to create a new instance of the camera. in our Game1 class and the following field and initialize it within the constructor.

```
// Our camera
Camera2D _camera;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
// Create our camera with 1280 with and 720 height
_camera = new Camera2D(1280, 720);
}
```

If you would like to instead create the camera using the `GraphicsDevice.ViewPort`

from within Game1, you can do this, but you'll need to create the camera instead in the `Initialize()`

method. This is because you need the `GraphicsDevice`

property to be set, which it will not be until Initialize is called.

Now, in our `Draw()`

method, we need to pass the transformation matrix from the camera into the spritebatch when we call `sprtiebatch.Begin()`

like so

```
spriteBatch.Begin(transformMatrix: _camera.TransformationMatrix);
// Draw things here
spriteBatch.End();
```

And that's it. You now have a 2D camera that you can use in you game projects. Don't stop here though, get creative. Think of some other things to add to your camera, like a way to smoothly move it from one position to another, or a way to "shake" it to give that sweet sweet screen shake effect. If you have some interesting things you added, let me know on Twitter and I'll add them here (with your permission of course).

And be sure to check out the project files for this tutorial on Github for to see a completed example of using the camera and moving it around with the keyboard.