2D Camera with Parallax Scrolling in XNA

Parallax scrolling is a technique that is frequently used in sidescrolling 2D games to give the impression of depth. It consists of making objects that are further away appear to move slower in relation to the viewer than objects that are near. Pay attention to your surroundings next time you’re on a moving vehicle, and you’ll notice that this also appears to happen in real life!

They say a picture is worth a thousand words, but with parallax scrolling you really have to see it in motion in order to appreciate it. So I’ll start by showing the video sample for this article right away:

There you have it. So, there are actually many different ways to achieve this effect, but I’d like to focus on the two that I find easier to use:

  1. Scrolling Textures – Useful for scenes like a starfield or a 2D sky. Somewhat limited beyond that.
  2. Camera Modification – General purpose and much more flexible.

Method 1 – Scrolling Textures

If you want to implement parallax scrolling entirely with repeating textures, then the easiest way is to use the technique described in my earlier article called Scrolling Textures in XNA. This is useful for instance to create starfields or 2D skies, but not as useful for games where the background needs to change constantly.

So let’s say you have three textures (texture1, texture2 and texture3) that you want to draw on top of each other and scroll them at different speeds. All you have to do is use the technique I described passing your camera position as your texture’s scroll position, and multiplying each of them by a different constant (e.g. 1.0f would mean full speed, 0.5f half speed, 2.0f double speed, etc.). Example below:

That’s all there is to it! And in case you didn’t notice, the video sample of my Scrolling Textures in XNA article already had parallax scrolling in it – there are in fact three layers of clouds moving at different speeds – although the effect is very subtle!

Update: I wrote a new article about this topic which lets you use zoom and rotation at the same time as scrolling the background infinitely. Check it out here. 

Method 2 – Camera Modification

Although using scrolling textures is quite easy, it is not applicable to all cases. Most of the time, your game world simply won’t be made up of repeating textures, but you’ll still want to leverage parallax scrolling. Other times you’ll also need the ability to move your camera around, rotate it and zoom it.

A couple years ago, David Amador wrote a popular article on how to create a 2D camera with zoom and rotation using a simple transformation matrix. I’m not going to describe the entire technique again here, so if you don’t already have a matrix based 2D camera implemented, you might want to start there in order to understand the basics.

It turns out that adding parallax scrolling support to a matrix based camera class is extremely simple (the video at the top of the article uses this technique). Here’s the entire camera implementation:

I simplified it as much as possible, but the only change made in order to support parallax was to make the GetViewMatrix method require you to specify the desired parallax factor (if you do not wish to have any parallax, simply pass it Vector.One), which is then multiplied by the camera’s position when calculating the view matrix.

The Origin Trick: I made another change in comparison with David Amador’s method (which is more a matter of personal preference) that was include an additional (negative) Origin translation matrix before the Rotation and Zoom matrices (I marked the code with a comment). I prefer doing this because it makes your origin calculations only affect zooming and rotating, but leave translation untouched. That’s because I prefer to set my camera’s position using the top-left corner, but still want to have it rotate and zoom around the center of the screen. This way you can have both at the same time! Also I recommend doing this since it makes some optional calculations (such as limiting the camera’s position or looking at an object) easier to handle, because you won’t have to factor in your origin.

What this means is that, for instance, if you pass it a Vector2(0.5f, 0.5f), objects will appear to move at half of their original speed, and if you pass it a Vector2(2.0f, 2.0f) they’ll appear to move twice as fast. As I mentioned above, passing it Vector.One means that there will be no parallax scrolling applied to that object, and passing it a Vector2.Zero will make the object stay in the same place even as you move the camera around. You can even pass different amounts of parallax for the X and Y axis if you wish!

Usage Scenario

Now, in order to use this class, simply instantiate it passing it your current viewport:

And use the GetViewMatrix method to get a transformation matrix for your SpriteBatch:

By the way, I’m not worrying about performance optimizations in this article for the sake of simplicity. In practice, you might not want to recalculate the view matrix every frame, and instead cache it and only update it when the camera changes. I’ll leave that exercise up to the reader, but if you need a tip just leave a comment below.

If all you wanted to know was how to implement parallax scrolling, then by now you should already have everything that you need. Below I’ll be describing some more advanced topics, which I believe should be worthwile to know, so I recommend reading to the end!

Optional: Layer Grouping

I find that the easiest way to handle different parallax values it to introduce the concept of layers. A layer is simply a group of game objects that share the same parallax value. Ideally you should be able to create as many layers as you want, set each of their parallax speeds, add your game objects to them, and just tell them to draw themselves. Here’s how I usually do it:

I’ll start by creatig a Layer class which has its own parallax speed, and holds a bunch of Sprite objects. Calling Draw will make all sprites be displayed with the correct parallax.

Here’s a minimal Sprite class implementation (for simplicity I stripped out rotation and scaling information, since it doesn’t serve any purpose in this example):

And here’s the Layer class. You need to already have a Camera object created when you create a new Layer, but after that it’s pretty straighforward. The only significant part is the call to SpriteBatch.Begin which relies on the camera to build a view matrix for the appropriate parallax value.

Usage Scenario

Putting it all together, you could for example setup a scene with 9 different parallax layers. Each of these layers will get a different parallax value, hold one sprite:

And draw everything with a simple loop:

And if you want to move the camera around, just use the properties exposed by the Camera class. All parallax magic will be done for you behind the scenes!

Frequently Asked Questions

Since I probably won’t be talking about the topic of 2D cameras again, I’ll take the chance to answer a few questions that I often see on the forums:

Q: When moving the camera around while it’s rotated, how do I make it follow the camera’s rotation?

A: You’ll need to do a little math for this. Add this method to your camera class:

Now whenever you want to move in accordance with the camera’s rotation, just set the “respectRotation” parameter to true!

Q: How do I make my camera look at some object, or follow my character?

A: Centering your camera around an object is simply a matter of settings its position to the same as the object, and subtracting half of the screen’s size from it (so you need to store your screen size inside your camera class. For this example I’ll assume that you stored a Viewport object in a member variable called _viewport). Here’s an helper method that will center the camera around some position:

Now if you want to make your camera always follow your character, all you need to do is add something like this to the end of your update loop:

Note: If you didn’t use my origin trick (explained earlier), then you’ll also need to add the camera’s Origin at the end in order to correct the offset.

Q: How do I make the camera stop moving beyond the edges of my level?

A: Okay, this is a bit more complicated, so I’ll go over it in a few separate steps.

First of all, just like the previous question, one thing your limiting code will need to know is how big your viewport is. So start by storing the viewport when you get it in the constructor for later use.

Next I’ll add a Rectangle property called Limits that lets you choose the extent of what your camera should be able to see. This extent should always be at least as big as the viewport. The question mark (?) after Rectangle makes it possible to assign it a null value. This isn’t normally possible because Rectangle is a value type. I made it this way so that setting Limits to null will disable camera bound limiting altogether. Here’s the code (notice how I validate the rectangle to ensure it’s always bigger than the viewport):

Finally, change your Position property so that its setter checks for the existance of a limit, and clamps the position accordingly. This technique as it stands doesn’t work so well when the camera is scaled or rotated, so I disabled the limiting behavior when the camera is transformed for the sake of correctness. But feel free to try to work around that limitation!

That’s it! Now if your level starts at (0,0) and has a size of (8000, 600) you can make sure your camera won’t leave that region by simply doing:

Even better is that if you combine this with the LookAt method described above, you will automatically get the common behavior where the camera seems to stop when your character reaches the borders of the map, and resumes again when you move away from the borders! No additional code needed.

Note: Once again, if you didn’t use the “origin trick” before you’ll also need to add the origin’s X and Y values to the Clamp calculation (inside the Clamp operations, on the min and max parameters).
Update: I wrote another article with more information about this matter. Check it out here: Limiting 2D Camera Movement with Zoom

Q: How do I find what position in the screen (or world) a certain point in the world (or screen) corresponds to?

This is common for instance when you want to pick objects on the screen with your mouse (screen to world), or to find out which objects are inside of your view (world to screen). If you have parallax scrolling, then this is something you’ll want to do at layer level (since each layer can have a different view matrix), but the general idea is still the same. If you don’t have parallax scrolling, just do this in your camera class instead with the appropriate changes!

This will get you the correct results, even if your camera is all rotated and scaled.

Conclusions

That’s all for this article. If you have any questions that I didn’t cover here, leave a comment below and I’ll do my best to answer them and update the FAQ accordingly. And as usual, you can find the source code for this article’s sample below. The camera class provided has all of the tips I described implemented, and I also included a SimpleCamera class (although I’m not using it) which is the bare minimum you need to get things working.

Source Code
65 Comments.
  1. Josh Jaques says:

    Pretty good ideas here.

    One other way to do the camera constraint is to set the default constraint rectangle to
    `new Rectangle(int.MinValue, int.MinValue, int.MaxValue, int.MaxValue)’.

    Doing it that way I think it simplifies the logic, since you don’t need all those checks if the constraint is null, you just apply the same checks every time.

    The downside vs. your method is that it’s harder to unset the constraint on a camera. Instead of setting the constraint to null, you need to expose the NO_CONSTRAINTS rectangle as a constant or something from the camera.

    • Indeed, that’s another way of handling it, but it also implies that the bound limiting code will be running every time, even if we don’t need it, which I think is the bigger downside here. This aggravates when the bound limiting code becomes more complex such as when trying to add scaling and rotation into the mix (which I didn’t describe here).

      Unless I replace the check by null with a check by NO_CONSTRAINTS, which will probably be worse than the original check by null.

      But your post made me realize something else, which is the possibility that our game world could be larger than int.MaxValue. In that case we could replace the Rectangle with a custom RectangleF class or two Vector2′s delimiting the camera’s Min and Max values instead in order to increase our range.

  2. Light says:

    dave like your site

    if you switch all those vector2′s to vector3′s
    you have a 3d camera right?

    also how would you scroll smoothly from the edge of the world to the right
    to give the appearence of wrapping around to the begining of the world

    or does this require that the world obj positions change to the opposite side of the world like a buffer area

    • Thanks for the comment :)

      1) A 3D camera is conceptually a bit different. You also need to calculate a view matrix, but this is usually done by choosing a position in the world and setting the camera’s up, right and forward vectors to define its orientation. The Matrix.CreateLookAt method makes this task a lot easier. Also, parallax is pretty much already done for you automatically in 3D by the perspective projection. So in general I’d say, this article is exclusively for 2D cameras.

      2) As for wrapping the camera, I’m really not aware of any simple solution for that problem. The reason for that is because when you go outside the edge of the map, you’ll want what’s on the *opposite* side to appear. This won’t be done automatically for you, so you need to somehow make this additional draw call yourself.

      I’ve never had to do this, but I think I’d start by trying something like what follows. Imagine your world is about seven screens wide ([1][2][3][4][5][6][7]) and you’re currently looking at [1].

      If your camera started moving to the left and exited the world border, you’d expect [7] to appear there, right? What we’d actually do is move the camera straight to [7] (with the right offset compared to where we were before the jump) and then draw a part of [1] to the right of it so that they appeared to be linked.

      In order to draw that part of [1] I’d use a render target. First position some extra camera on [1] and draw the scene to a screen-sized render target from that point of view.

      Then simply draw both the normal scene (which would be showing a bit of [7] on the left) and the render target (which would be showing a bit of [1] on the right) side by side, so that we end up seeing [7][1] with the camera somewhere in the middle.

      Finally, once the camera moved far enough to the left for no remains of [1] to be on screen, simply stop doing this extra processing. You only need to do it in that little transition zone between the borders.

      Then simply reverse the process when going out the right side of the map.

      Maybe I’ll implement it and post a sample one of these days.

    • Okay so I just tried implementing the wrapping camera with my description above and it worked well, and wasn’t that hard to implement.

      But there’s one detail that I missed out. Any sprite that *intersects* the border of the world (that is half in each side) needs to be drawn twice (on two different positions) otherwise they appear chopped in half.

      I’m still trying to figure out an elegant way to handle this case, although the brute force method is already working, which is:

      1) If sprite intersects left border, draw him at his current position and his current position + world size.

      2) If sprite intersects right border, draw him at his current position and his current position – world size.

  3. Joe Pinner says:

    I have just started looking into XNA and C# myself ready for my next year at University. Just from making a few little games like pong, tetris, minesweeper and snake I feel my programming skills are coming along nicely. I was going to attempt to make a side-scrolling game as my next project so really appreciate you putting up this tutorial. Good luck with your blog! :D

    • Hello Joe! I took a look at your website, and you’re definitely doing everything right by starting small and moving up progressively. You’ll be doing some great projects of your own in no time. Good luck for you too!

  4. Matt says:

    David,

    I’ve tried implementing something similar to your camera method, but I have a few specific circumstances that I’m not sure about:

    I would like to tile several smaller sprites in the background to create a scrolling star field effect, however, zooming and rotating the camera greatly complicate this, as it’s not entirely clear where to begin tiling and end tiling. Obviously, I could just tile the whole level, but this is very slow. Do you have any suggestions for doing this efficiently?

    Thanks
    Matt

    • Hello Matt,

      I’m not sure if I completely understand your problem, but if you read the first part of my article, I present an easy way to create scrolling backgrounds that is just great for things like starfields, and it doesn’t even need a camera for it. I also describe it in more detail here. Have you tried that? The catch is that it uses one texture for each layer of parallax. On the other hand you mentioned “several sprites”. Well nothing that can’t be handled.

      If possible try to give a concrete example of what you’re trying to do, but for now I’ll make the assumption that you have a bunch of star and planet sprites, and what them to repeat periodically on the background, possibly at different speeds:

      In that case what I would do is start by creating a different RenderTarget2D for each of my background layers. Then on my initialization I’d draw my sprites into each of the render targets, in whatever positions I’d want them to be. By the end of it I’d have one texture for each layer, and would be ready for the technique above. In other words I’d simply use the SamplerState.LinearWrap trick to do the scrolling and tiling for me.

      Now, I’ve never tried mixing that with zooming or rotation. As for zooming, I don’t think it would make much sense, because since the starfield is supposedly so far away, no matter how close you got your ship, the stars shouldn’t appear any bigger. As for rotation, you only need to rotate the background textures when calling SpriteBatch.Draw on them. Just make sure the rectangles you draw are big enough to fill the entire screen even when rotated.

  5. Icebox says:

    I’ve implemented a parallax scrolling solution not dissimilar to your first method (more like your first, aborted attempt, to be precise – might have to go back and fix it) but now I’m truly stuck.

    I’m making a horizontal 2D shooter in the vain of Gradius and R-Type, but I’m completely confused about how a camera might work in this context. I mean, assuming there even IS a camera at being used in this type of game, its movement and speed doesn’t appear to bear any relation to the ship’s position – and yet the ship always stays on the screen.

    I just need SOME advice on this – not even code, just a principle to work from. I understand how it works in a platformer because it’s just tracking player movement, but maybe that’s the problem – I just can’t conceive of how it applies to a shooter.

    Excellent article, by the way. There’s a real shortage of info out there for budding XNA developers like myself, and I suspect this will be a big help to them (it was to me, at least).

    • Edit: Read the posts below, which present a better alternative to this problem.

      It’s actually quite simple. If you take a closer look at one of those games, you’ll notice that the background is always scrolling at a constant speed regardless of what the player does. So, I would recommend NOT using a camera at all for this. What you need is:

      1) A scrolling background class implemented like the first method I describe in this article. It should hold a couple of star textures which it will scroll from right to left (at slightly different speeds), and it should also expose some Speed property to control how much it should be scrolling each second.

      2) There is no camera. The ship is always on screen and can move whatever way it wants, the only thing you need to prevent it is from leaving the screen.

      3) You define your enemy classes describing how each of them should behave and what is their dying condition (should they stay on screen until killed by the player, or should they exit the screen after some time and die?). Basically each enemy knows how it should move, how it should attack, and how it should die. But one thing the enemy doesn’t know is when to appear.

      4) Then you need to create enemies at the right places, at the right times. Remember the Speed value of your background class? You can use that as the basis for a timer that tells how much the ship has moved so far. So for instance every frame you’d do:

      // Assuming float timer = 0f;
      timer += background.Speed * elapsed;

      And use that timer to know when to trigger new enemies. You could have a file that would be something like (I’ll write it in natural language for better comprehension but you should just keep the needed information):

      At time 20 spawn Red Octopus at (800,300)
      At time 22 spawn Demon King at (0, 100)
      At time 28 spawn Red Trooper at (800, 100)
      At time 28 spawn Red Trooper at (800, 300)
      At time 28 spawn Red Trooper at (800, 500)

      You load this file into a list, ordered by time, and each frame you check the front of your list against your timer variable to know if it’s time to spawn a new enemy or not.

      5) Finally, besides the background you might also want to have some scenario from time to time. For this I would create a List of scenario objects, where each object has a Texture and a Position in the WORLD (not in the screen). Then I would use the timer variable above (which basically tells your position in the world) to figure out which images to draw, and in what position. This would make them scroll along with the screen.

      That’s probably how I would do it, although I’ve never implemented a sh’m'up so far. What do you think?

    • On further thought, I think you could also use a normal 2D camera too, but keep the background independent from the camera.

      So first you’d have the scrolling background drawn outside the influence of the camera.

      Then have a 2D camera moving right at a constant speed, and ADD that same speed to your ship, so that it looks like it’s not moving.

      If you press the arrow keys, add something on top of that speed, but make sure you clamp the ship’s position to what the camera can see (if you’re not using zoom, simply clamp to Camera.Position / Camera.Position + Screen.Size).

      Enemies and background are all added to the world at their correct positions from the start, but with two catches:
      1) You only draw what the camera can see. Do a bounds check to occlude the rest.
      2) You only start updating your enemies once they come in sight, and kill them after they leave the screen on the left.

      Yeah, I think that could work too.

    • Icebox says:

      Thank you David, you’ve given me a lot to think about (more than I ever came up with on my own).

      I think I’m going to try and make your second suggestion work for my game. I’m pretty new to both coding and game design, so while the first option would probably suit me better, I get the feeling that designing levels using co-ordinates and time indeces will probably drive me insane.

      Also, I imagine using a camera in conjunction with a tile engine would make things much easier (although I could be wrong), if only because I could visually plan out the level.

      Thank you again David. Consider yourself bookmarked. :)

    • Glad I could help.

      And yeah, I think my second idea will actually work out better for you too, especially when coupled with a tile engine! You could basically lay out all of your scenario and enemies in a tile editor and the rest should be pretty easy to implement!

      For the background, since it becomes tile based, just use the usual code to decide which tiles to draw based on the camera’s bounds.

      The enemies and powerups are handled separately because they can move smoothly between tiles, but their starting positions could easily be defined in the tile editor too.

      Handling enemies spawn, update and draw shouldn’t be too complicated either. For example, you could have two lists, one for sleeping enemies and one for drawing.

      You’d start by adding all your enemies in the level to the sleeping list. Then whenever an enemy on the sleeping list came into view, simply wake him up (i.e. remove him from the sleeping list, add him to the drawing list, and start updating his AI).

      Finally, whenever an enemy dies (either by moving out of the screen again or being destroyed by the player) just remove it from the drawing list and you’re done with it. Same thing for powerups.

  6. Josh Jaques says:

    Matrix.CreateScale(Zoom)

    This line was a problem for me since I use depth sorting of my sprites. What that line does is actually create a matrix which scales x, y and z equally. I found spritebatch would clip any sprite with a scaled z value > 1.0, causing them to disappear on me once I zoomed in a certain amount.

    What most people want is a matrix which scales x and y without touching z:

    Matrix.CreateScale(Zoom, Zoom, 1)

    • Indeed, I noticed Shawn’s reply on this subject, and have been meaning to upgrade both this article and my engine. I’ll get to it today, thanks!

  7. Zikomo says:

    Came across your post recently and it was a great starting point for what I needed to do. Just to add one thing that may be interesting is parallax zooming which gives the camera a bit more depth when zooming or moving “into” the image. It’s pretty easy to implement in your code by simply modifying:

    Matrix.CreateScale(Zoom)

    to

    Matrix.CreateScale(1 + Zoom * parallax.X * 2)

    I also set the default Zoom from 1.0 to 0.0 to make this work the way I expected.

    • Hello, and thank you for your comment.

      I did think about parallax zooming when writing the article, but decided to leave it out this time. But you’re right, it’s pretty trivial to implement. Just find a way to modify your scale matrix, to a greater or lesser degree, depending on the current zoom value.

      And as a side note, check the comment right above yours for a little bug that can happen when you’re also scaling the Z coordinate of your sprites along with everything else.

      Take care!

  8. John says:

    I’m wondering how one might prevent sprites that are not visible from being drawn.

    • What you’re asking about is a concept usually known as “culling” in game development. More specifically, you’d like to perform a “viewing frustum culling” which means remove everything that can’t be seen by the camera from the drawing list. You should google a bit about the subject and something should show up. But here’s some ideas of how I’m currently doing it.

      Since this is 2D you don’t need a frustum to represent the viewing area – a single rectangle is enough. Whether you should use an axis aligned rectangle (vector2 min + vector2 max) or an oriented rectangle (vector2 extents + matrix transform) depends on whether your camera and your sprites can rotate or not.

      You calculate a rectangle (axis aligned or oriented) for the camera and for each of your sprites, and when drawing each sprite you check to see if the camera rectangle intersects or contains the sprite rectangle. If it doesn’t, then you skip drawing that sprite.

      Intersecting oriented bounding rectangles is not that trivial, so I prefer to convert my oriented bounding rectangles to simple axis aligned rectangles (for which I use a class similar to RectangleF from the Nuclex Framework http://nuclexframework.codeplex.com/).

      To convert an oriented rectangle to a normal rectangle I calculate the coordinates of each of the rectangle corners, and then find the minimum and the maximum x and y values from all four points. This results in the smallest axis aligned rectangle that is big enough to fit the oriented rectangle inside.

      So to sum it up… It’s a bit hard to explain this in the comment section so you should research it a little yourself, but the idea is to get a mathematical representation (a rectangle) for your camera and for each of your sprites, and see if they intersect/contain before drawing.

  9. Oshri says:

    How do i add a player into the project? >.<
    and i want the camera to follow the player… to track it or whatever its called..
    Thank you for this, i like your website.

  10. TemporaryName says:

    I’m having a problem with the line:

    spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, camera.GetViewMatrix(parallax));

    I had put it in my Game1.Draw method. Initially i assumed it was spritesortmode.deferred, so i made the following changes:

    >At the top of the class:
    SpriteSortMode deferred;
    Vector2 parallax;

    >In my initialize method:
    Vector2 parallax = new Vector2(0.5f);
    SpriteSortMode deffered = SpriteSortMode.Deferred;

    >in my Draw method:
    spriteBatch.Begin(deferred, null, null, null, null, null, camera.GetViewMatrix(parallax));

    But I’m still getting this completely not-helpful error code. Any ideas?

    • You’ll need to tell me what error you’re getting. I’m sure the error message should tell you exactly what the problem is. As it stands it could be so many different things… For instance:

      1) Since you declared “parallax” and “deferred” at the top of your class (and by the way you really should just be using SpriteSortMode.Deferred directly on the SpriteBatch as it was before), then if you want to assign a value to them inside some method (such as the Initialize method) you *shouldn’t* be declaring them again! In your example, you’re using the wrong syntax. What you did instead was create two entirely new variables inside Initialize’s scope, instead of assigning the values to the ones existing on Game1′s scope. In other words you should do:

      // Inside Initialize
      // Notice that you don’t repeat “Vector2″ here
      parallax = new Vector2(0.5f);

      But there’s no need to even use the Initialize method for this, since these values are not dependent on XNA being initialized to exist, you could just declare and initialize them on the same line at the top of your class, such as:

      // Inside the class but outside any methods
      Vector2 parallax = new Vector2(0.5f);

      2) Did you copy paste that from your code? If so, check your spelling. You used “deffered” once and “deferred” in another place.

      3) Did you create a Camera object and initialize it? I.e. you need to do:

      // Top of class
      Camera camera;

      // On LoadContent
      camera = new Camera(GraphicsDevice.Viewport);

      And of course, the Camera class should exist on your project too.

      4) You could be using XNA 3.1 instead of XNA 4.0, which would imply an entirely different interface for the SpriteBatch.Begin method.

    • TemporaryName says:

      Hey, thanks mate. What I was doing wrong was using
      Camera camera = new Camera(GraphicsDevice.Viewport);
      Making a NEW instance of Camera. Learned quite a bit from this. thanks. :)

  11. Amo says:

    Can you please help me with the following:

    im trying to add a camera to my wp7 game in xna 4.0 to follow the player.

    I have implemented the code but in i am getting a error.

    at the top of the class ive put Camera camera;
    and used all the relevant stuff from the tutorial

    i am getting an error: game1.cs.Game1.camera is never assigned to, and will always have its default value null.

    any suggestions?

    in loadcontent:
    Camera camera = new Camera(GraphicsDevice.Viewport);

    in update:
    camera.LookAt(playerposition);

    in draw:
    spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, camera.GetViewMatrix(parallax));

    dont know what im doing wrong… im still pretty novice/beginner at coding, any help would be great.

    • Hello there!

      The problem you’re having is exactly the same as the person who posted before you. I’ll start by giving you the solution, and then try to explain the problem. So, to solve the problem, you need to go to your LoadContent method and change what you already have to:

      // Notice that you don’t repeat “Camera” here
      camera = new Camera(GraphicsDevice.Viewport);

      Now to try and explain why it didn’t work, let’s start with a simplified version of what you currently have (nevermind the dots, I just put them there for identation):

      class Game1
      {
      ….Camera camera;
      ….public void LoadContent()
      ….{
      ……..Camera camera = new Camera(GraphicsDevice.Viewport);
      ….}
      }

      In this example you’re creating two separate variables called “camera”. The first one is declared at “class scope” so it is accessible anywhere inside the class. The second one is being created inside LoadContent method and only exists inside that method. Let me rewrite that example for you, in a way that works exactly the same, but should make it easier for you to spot the mistake.

      class Game1
      {
      ….Camera camera;
      ….public void LoadContent()
      ….{
      ……..Camera camera;
      ……..camera = new Camera(GraphicsDevice.Viewport);
      ….}
      }

      Can you see now that there are two different “camera” variables being declared? So when you’re assigning it a Camera object using “new” the variable that is declared inside the method takes precedence, and the one declared outside is never assigned anything. So the camera variable stays as null and everything else crashes when trying to operate on it. That’s also why the compiler gave you that warning about “camera” never being assigned.

  12. Amo says:

    hello, thanks alot for that, i did read the above post and solve some of my problems from there, thank you for your clear description. it makes perfect sense to me. i did try it before but i didnt have the rest of the code correct, so it threw an error. now its is fine. thanks.

    Next step will be to get the camera following my player, which should be no problem thanks to your brilliant tutorial.

  13. Amo says:

    i think you knew this would be coming lol…
    Help again please.

    In my player class i have public vector2 playerposition;

    and the sprite is drawn with:
    spriteBatch.Draw(player, playerposition, Color.Green);

    using the game class and my control system, i have full control of the player using player2.playerposition.X etc,
    player2 being the Player class.

    i have modified you follow the character code so that it reads (in the camera class)

    public void LookAt(Vector2 playerposition)
    {
    Position = playerposition – new Vector2(viewportwidth / 2.0f, viewportheight / 2.0f);
    }
    i have added to my game update

    player2.Update(gameTime);
    // Updates your camera to lock on the character
    camera.LookAt(player2.playerposition);

    cant seem to get the camera to follow?

    • Well, it could be a few things. First of all, why did you change the LookAt method?

      There’s no difference when you change the name of a method parameter (i.e. you changed position to playerposition in the method signature, which makes no difference because that’s a parameter which already acts like a local variable to that method and has no connection to the “outside”).

      Also the camera was supposed to hold a Viewport object (which I named _viewport) and use its Width and Height properties to get its size. I see you changed it to viewportwidth and viewportheight. Are these values being initialized? Have you verified that they are not zero?

      Also are you sure your “parallax” value is not zero? You should set it to “Vector2.One” or “new Vector2(1.0f)” because if it’s zero, the camera won’t move at all.

  14. Paolo P says:

    I came across your article and the codes really help a lot with the game I’m working on. There’s a few questions to ask though. Sorry for my bad grammar in advance.

    I’m making a spaceship game that moves in all direction and uses a jpeg file as a background screen. I did a parallax scrolling only the background screen. I wanted to add a keyboard control to zoom in or zoom out the screen but if I keep zooming out, I notice that I could see whats beyond the edges of the screen, which is not what I want. How could I limit the camera to fit the bgscreen even after I zoom out? Changing the jpeg file into a bunch of sprites as a background is a hassle though.

    • Hello!

      I’m not sure I really understood the problem you’re having. When zooming out do you want the zoom to stop once the background no longer fits on screen? Or do you want the background to repeat itself infinitely in every direction?

      For a spaceship game I suppose the second alternative sounds better, so I have to ask if you’ve read my other article called “Scrolling Textures in XNA”? As I explained here, that technique is more appropriate for spaceship games.

      Using that technique you make the background scroll in response to the camera, and to add parallax you only need to multiply the background’s position by the parallax factor. As for supporting zoom out, you’ll need to do a few calculations and adjust the source rectangle and destination rectangle parameters of SpriteBatch Draw according with your camera position and zoom, in order to make it scroll and fill the screen correctly.

      Basically, your destination rectangle will always be (0, 0, screenWidth, screenHeight) and your source rectangle will be be (x,y,w,h) where x,y are based on your camera’s position, and w,h will be the screen’s size divided by your zoom. I.e something like:

      Rectangle destination = new Rectangle(0, 0, viewport.Width, viewport.Height);
      Rectangle source = new Rectangle(camera.X, camera.Y, viewport.Width / camera.Zoom, viewport.Height / camera.Zoom);
      spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.LinearWrap, null, null);
      spriteBatch.Draw(texture, destination, source, … etc …);
      spriteBatch.End();

      I haven’t tested it though, will try it out later.

    • Paolo P says:

      Thanks for the reply. I want the background to fit everything on to the screen after zoom and will stop once the background no longer fits on screen. So far I manage to resolve this by using the source and destination rectangle but this also made new problems. Things like clamping an object’s position within the screen or that the program draw the bg itself infinitely. So I tried coding it like this in the Position method:

      _position.X = MathHelper.Clamp(_position.X, Limits.Value.X + Limits.Value.Width * (1 – Zoom) / 2, Limits.Value.X + Limits.Value.Width * Zoom + _viewport.Width – Limits.Value.Width * (1 – Zoom));

      _position.Y = MathHelper.Clamp(_position.Y, Limits.Value.Y + Limits.Value.Width * (1 – Zoom) / 2, Limits.Value.Y + Limits.Value.Height * Zoom + _viewport.Height – Limits.Value.Width * (1 – Zoom));

      which is probably wrong but its closer to what I want

    • Roger. Doing that is a bit more elaborate so hang on a bit, I’ll write an explanation up, and post it as a new blog post since it will probably be too big for a comment. :)

  15. Mister G says:

    Hello, I found the article very helpful, but I can’ t figure out how to make each layer repeat infinitely (like in a spaceship game but with a camera), I mean, if I scroll the camera along the level, when I reach the end I will be able to see the “blue background”. Instead of that, I want another layer to show up as soon as the blue background is visible.

    Thanks in advance

    • Hello,

      That’s the special case that I talked about which is easier to implement using Method 1 instead of using a view matrix (Note: I describe that method in my other article “Scrolling Textures in XNA”). You can draw the other layers with Method 2, but draw the infinite layer separately (before everything else) using Method 1 instead.

      This method consists basically of the following – you need to start your SpriteBatch using SamplerState.LinearWrap instead of the default which is Clamp. This makes it so that any texture coordinates that fall outside of the 0-1 range are wrapped i.e. your texture repeats infinitely. Then the only thing you need to do is set the Draw’s destination rectangle to be your entire viewport, and your source rectangle is the place where you do your parallax calculations – the rectangle’s x/y properties will be the camera’s position multiplied by your desired parallax, and the rectangle’s width/height are will be your viewport’s size multiplied by your camera’s zoom. I think that should work.

      I’m not t sure how to fit rotation in, do you need it?

    • Mister G says:

      Thanks for your reply, it’ s much easier than the solution I thought (which was quite a mess).
      Btw, i won’ t be using camera rotation in my game. Thanks again.

    • Hey, check the front page anyway. I just wrote about a new technique that works with rotation and origin and should be more robust. :)

  16. Minh-Thuan Bui says:

    Dear David Gouveia,

    Thanks for your article! It helped me solve some problem with my game.

    I have had some trouble. I have a background, width of it is 2048 pixel. I want to create a background load continuously with width double 2048 pixel . Could you help me!!!

    Thanks so much!

    • Hello, and thank you for your comment!

      You mean that you want to make a 4096 width background wrap infinitely? Like in my Scrolling Textures article (http://www.david-gouveia.com/scrolling-textures-with-zoom-and-rotation/)?

      I’m sorry but I’m actually not really sure either what would be the best way to solve that problem. I’m relying on the graphic card’s texture addressing modes to create wrapping backgrounds, which means that your background must fit inside a single texture. However, there’s a limit to the size of the textures you can load. If you’re working in the Reach profile, that limit is 2048×2048. If you’re working on HiDef profile that limit is 4096×4096 so it’s enough for your case, but not for the general case (http://blogs.msdn.com/b/shawnhar/archive/2010/03/12/reach-vs-hidef.aspx).

      If all you want is a 4096 texture, and you can change to HiDef mode (it’s an option on the XNA project properties), then you might want to do so. But I’m still trying to figure out a general solution. Ideally, that solution should be able to open a texture of ANY size, internally split it into multiple textures of the maximum supported size, but still provide all the operations that you’d expect on a regular texture as a whole.

      But if you don’t need a general solution, you could also try doing the repeating manually. Split your 4096 background into two 2048 textures and draw them side by side. Then depending on where your camera is looking at, adjust the position and order in which you draw each of the textures so that they always fill the entire view and give the illusion that it’s all one continuous background. I don’t know the exact procedure for this, I always implement this sort of stuff with trial and error, drawing on paper and stuff, but it should be fairly easy to get it working. And if your camera can zoom out, then you might also need to draw the textures more than two times to fill the entire screen.

    • Minh-Thuan Bui says:

      Thanks for your reply! It’s so helpful for me!!!

  17. Davis says:

    Great article! Really improved my camera for my game.

    Do you know how I can have all my rotation and things, but no zoom. I want most items to rotate with the camera, but some to not. For example, if I’m making an rpg (I wish) then when the user rotates the world the trees should not rotate, but still be upright. They should still move with the camera. A good example of this is realmofthemadgod.com if you go into a realm then the trees do not move, when you have camera rotation on in the settings (press esc) then press q and e. The trees do not rotate with everything. I don’t want upside down trees.
    Any ideas?

    • Hello, thanks for visiting. Yes I have an idea how to implement something like that. The concept is a bit like billboarded sprites, but in 2D, and is something you’ll want to implement on your objects (i.e. as a special feature of your sprites) and not on the camera. As you probably know, the view matrix you get from the Camera modifies everything in the world. You can’t just turn it off for a few of the objects. What you can do is make those objects “counter” the effects of the camera with their own transformations. Assuming you already have a Sprite class in place, start by creating a subclass of it called BillboardedSprite for instance. The most important part of this new class is that it should take a reference to the Camera in the constructor. Then in the Draw method you should make use of the camera.Rotation and camera.Scale values to give the impression that it’s never transformed. For example instead of drawing with rotation “sprite.Rotation”, draw with rotation “sprite.Rotation – camera.Rotation”. Instead of drawing with scale “sprite.Scale”, draw with scale “sprite.Scale / camera.Zoom” (I’m not sure about the “direction” of these operations, so if – and / don’t work, try changing to + and * instead).

  18. James Earl says:

    Thanks for the wonderful tutorial David, I do, however have a question. I’m making a game which would have multiple characters on the screen at anyone given time, I need to use Zoom to make sure all the characters are on the screen. How would i be able to Zoom out slightly, but still make sure the camera stays within the game bounds?

    So basically, 2 characters move away from each other, they reach the end of the screen, and keep moving, instead of the characters not being visible, the camera Zooms out to keep them in view. This is fine if it happens in the middle of the background image, however, if ones at an edge (Characters are clamped to the size of the background to keep them inside the game field), but the camera would need to zoom out and still stay within game bounds

    I’ve probably wrote this in the most complicated way, but thanks a lot if you have any answers, or information to where i could find a solution to this problem.

    James

    • Hello and thank you for stopping by.

      About your question, I think it shouldn’t be too hard. For starters head over to this other article to make sure you have the most recent implementation of camera bounding in place. Start by setting the camera bounds to be your game room, which will unsure that no matter how much you zoom your camera out, it will never stop being valid. With this layer of protection in place, you can go around tweaking your zoom value to get the effect you need.

      So, the next step is finding the minimum zoom you can have so that the players are both visible. Take a look at my ValidateZoom() method in the other article, because the concept is extremely similar. You know that at Zoom 1 your camera can see exactly one Viewport.Width pixels horizontally. And you also know the distance between your players. So the only thing you need to do is something like dividing the viewport width by the distance between both characters to get the correct zoom value, and then positioning your camera on the center position between both characters. Study the other article a little and see if you can make it work. Good luck!

  19. Néstor García says:

    Hey David, I really like this tutorial so far :) I was wondering, do you think this could somehow be adapted for a 3D game? I’m working in a 3D side-scroller game (like the old Altered Beast from Sega Genesis, but all with 3D models) and the camera I want to use is one with 2D perspective. Thanks for your answer!

    • Hello! I think it’s possible and it shouldn’t be too different. The thing with 3D is that you also need to create a projection matrix along with your view matrix. But since you’re drawing from a 2D point of view instead of creating a perspective projection matrix you might want to create an orthographic projection matrix instead if you don’t want your scene to have depth. The Matrix class already has some static methods that help you create an orthographic projection matrix. As for the view matrix I think you can use something similar to the one I describe here, or you can use the Matrix.CreateLookAt method with the correct parameters to set one up for you.

  20. Francisco says:

    I tryed to use this system in conjuction with a tilesystem I made myself.. and when I move the camera, or rotate it, or zoom… I get little spaces between the tiles… How can I solve this?!
    I think I get this from floating point positions… but when I cast them to int the camera movement becomes floppy and not so smooth.
    I heard of drawing everything to a RenderTexture and then draying the texture to screen.. but I don’t know how I can do this.. is this the only way? can you give me some help, please?

    Thank you very much

    • Can you isolate the problem into a new, minimum XNA project and post it somewhere? I’ve been asked this before, but I’ve tried recreating this problem, and I never see any gaps on my side no matter how much I zoom or rotate the camera. So it would help if I could experiment with the problem directly.

    • Francisco says:

      Here it is the trimed project! :)

      http://www.4shared.com/rar/a4NshMkm/Tile.html

      thank you in advance!!

    • Francisco says:

      Maybe I’m using a bad tile system implementation… if so, if you could give some orientation :)

    • Francisco says:

      I think the code i’m using for the tilesheet to return the correct rectangle is wrong :) but I corrected it so now I think it’s okay.. but either way.. if you thinks there is a better way to implement the tile engine… please let me know :D

  21. ChrisK91 says:

    Hi David,

    thank you for this excellent tutorial. I just started developing with XNA. As a start project I’m trying to create a small 2D shooter for Windows Phone. Therefore I want to use both infinite and finite parallax scrolling textures. However I’d like all the textures to rotate and zoom. I created a class inherited of the Layer class that uses the first approach to scroll textures:

    public class InfiniteLayer : Layer
    {
    public InfiniteLayer(Camera2D cam)
    : base(cam)
    { }

    public override void Draw(SpriteBatch spriteBatch)
    {
    spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.LinearWrap, null, null, null, _camera.GetFixedMatrix());
    foreach (Sprite sprite in Sprites)
    spriteBatch.Draw(sprite.Texture, sprite.Position, new Rectangle(Convert.ToInt32(_camera.Position.X * Parallax.X), Convert.ToInt32(_camera.Position.Y * Parallax.Y), sprite.Texture.Width, sprite.Texture.Height), Color.White);
    spriteBatch.End();
    }
    }

    Basically the textures are working fine. However I think that they are scaled down way too much. I think that I multiply the zoom factor too often. But there is another problem: The textures are not drawn over the entire screen.

    http://i49.tinypic.com/zipxmg.png

    The additional camera code is:

    public Matrix GetFixedMatrix()
    {
    return Matrix.CreateTranslation(new Vector3(-Origin, 0.0f)) *
    Matrix.CreateRotationZ(Rotation) *
    Matrix.CreateScale(Zoom, Zoom, 1) *
    Matrix.CreateTranslation(new Vector3(Origin, 0.0f));
    }

    • Hello,

      There’s a few things you need to change. First of all, for infinite layers like this you can not use the camera matrix, like you do with regular layers, you should simply use Matrix.Identity. It’s the values in the source rectangle that will make the image scroll and zoom, not the matrix.

      Then for it to cover the entire screen your width and height in the source rectangle must be the width and the height of the screen, not the width and height of the texture as in your example. And you must draw them with position equal to Vector2.Zero so that it starts from the top-left corner and covers everything.

      Using the source rectangle, you can scroll it and apply parallax by modifying the X and Y properties of the rectangle like you’re already doing, but you can also zoom by multiplying the Width and Height of the rectangle by the zoom value. As for rotation, you’re going to get into trouble trying to do it in Windows Phone because you can’t use custom shaders… I have two articles on my blog about texture scrolling, one of them with rotation implemented, but unfortunately it requires a custom vertex shader. But give them a read anyway.

  22. LDL says:

    Hey, David!

    I’m trying to get the camera to lock on my character like you explained in the second question of the FAQ, but it doesn’t seem to be working for me.

    What seems to be happening is the camera scrolls at the same rate that the character moves (i.e. if my character moves 10 pixels at a time or 5 pixels at a time in any direction, so does my camera), but the problem is my character is also moving at this rate within the camera’s view. In other words, the camera pans correctly, but the character will still move off the camera.

    Any ideas what I could be doing wrong?

    • Hello!

      I’m not sure I understood the problem, because you started by saying that the camera is scrolling at the same rate as the character. If they were indeed scrolling at the same rate, the position of the character within view would never change, so it would be impossible for him to leave the screen. But I can foresee a situation where this problem would happen, which is if you were drawing your character with a parallax value different from 1. Is that the case? If it is, you really should only apply parallax to the background or foreground, not the character or objects layer, otherwise you also have to multiply the parallax value by the character position when assigning it to the camera.

      It would be easier to find the reason if you could paste the relevant portion of the code in a pastebin. :)

    • LDL says:

      Sorry if my wording wasn’t the best and I apologize if my clarification isn’t any better, but what I was trying to say is that my camera moves 5 pixels at a time to the right if I move my character to the right which is what my character is programmed to do (move 5 pixels at a time), but my character is moving 5 pixels to the right compared to the camera’s view, so compared to a layer with 1.0f parallax, the character would essentially be moving 10 pixels to the right while the camera only moves 5, which is odd because I displayed both the camera’s and character’s position and they are both increasing at the same rate (5 pixels at a time). Also, I didn’t draw my character based on any parallax values. But I think that’s the problem.

      You said, “…you really should only apply parallax to the background or foreground, not the character or objects layer…” and that made me realize that my character is being drawn separate from any layer. So basically I should be putting my character in one of the layers (a layer with a parallax of 1), right?

    • Well what I meant is that when drawing the characters, you should use a view matrix that does not have any parallax on it. It doesn’t really have to be a “layer” or anything. But the way you’re describing it, it looks almost as if your character is being drawn with a view matrix that has parallax 2 instead of 1.

    • LDL says:

      Oh! I had my character class written up before I implemented anything else including the stuff in your tutorial and so I had a basic:

      spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);

      in the draw method for it, so it wasn’t getting drawn using a view matrix. It’s working now, thanks!

  23. John says:

    Hi,

    I’ve implemented a nice 2D parallax scroller using layers and animated sprites and such, and your nice camera class. Each layer “owns” the sprites and Draws itself and it’s sprites etc, etc.

    I was wondering if you had any thoughts on how to prevent sprites that are outside the camera’s “view” from being drawn.

  24. Jens-Axel Grünewald says:

    Would it be possible to render the layers with calling spritbatch.Begin() / .End() only once?

  25. ric says:

    Hi David,

    Thanks for the tutorial!

    I have a question regarding the origin trick;

    In the method GetViewMatrix, the attached source negates the translation, and you mention this set camera’s position using the top-left corner.

    When the game loads, I have calling cam.LookAt() and passing in the player’s position in the update section. Should the player (assume he starts at 0,0) appear on the top left of the screen, or in right in the center?

    Thank you for your time.

  26. Sam Rothermel says:

    This works very well. Thanks for the tutorial!

  27. Denis says:

    Hi David,

    I’ve just recently started messing with cameras in a 2D XNA game and your article was a great help to get us off the ground. I’m having some trouble fully understanding all the math concepts so I was wondering if you could give me some quick advice.

    We are actually using the camera as a way to handle different resolutions. We are targeting a “real resolution” of 1920×1280 and if the user’s screen is less, we zoom to scale. Here is our transform method:

    if (!_updated)
    return _transform;

    _transform =
    Matrix.CreateTranslation(new Vector3(-_pos * parallax, 0.0f)) *
    Matrix.CreateRotationZ(_rotation) *
    Matrix.CreateScale(new Vector3(_zoom, _zoom, 1)) *
    Matrix.CreateTranslation(new Vector3(_realPos, 0.0f) * new Vector3(parallax,0f));

    return _transform;

    Essentially, _realPos is the real screen resolution and _pos holds the “actual” which is 1920×1080. I’m having a few issues here. Even though we aren’t implementing parallax at the moment, I’d like to have the code in here for future projects (and would like to implement resolution scaling the same way). Currently, this block of code will also seem to apply parallax to scaling. What would be the math to remove parallax from scaling in this case?

    2nd Question, one reason we decided to implement the camera is because I’m having some issues scaling XNA effects during a spritebatch draw call. We have some alphatesteffects that need to be projected onto the screen correctly. Alphatesteffect has World,View, and Projection properties. What is the best way to apply our camera so the alphatesteffect will follow our scaling pattern mentioned above?

    Thanks a ton in advance… I’m just not very saavy with all these matrices just yet.

  28. tuttoscorre says:

    Hi and thanks for your tutorials. I have a little question relating to this tutorial, can you please read it for a moment and give me your opinion, please?

    http://gamedev.stackexchange.com/questions/62030/parallax-scrolling-with-2d-camera

    Thanks a lot. If you want you can just put an answer here or by email.

    Thanks a lot

  1. By Limiting 2D Camera Movement with Zoom | David Gouveia on September 10, 2011 at 1:48 am

    [...] my “2D Camera with Parallax Scrolling in XNA” article, one of the topics I described down in the FAQ section was how to limit the range of [...]

  2. By Scrolling Textures with Zoom and Rotation | David Gouveia on September 20, 2011 at 12:53 am

    [...] already written twice before (here and here) about a way to make a texture seem to repeat itself infinitely in every direction as you moved [...]

  3. By Side Scroller - XNA (C#) JoePinner.co.uk on September 30, 2011 at 1:46 pm

    [...] We have implemented a 2D camera with parallax scrolling as described here. [...]

Leave a Reply