Best practice for using a camera in MonoGame?

What is the best (Best balance between efficiency & simplicity) way to implement a camera in MonoGame? Currently I am just applying a vector to all sprites that are dependant on the camera (Tiles, enemies, etc.), but it is really tedious to pass in a vector to all sprites. I know that you can use a TransformMatrix in a SpriteBatch, but then you need multiple SpriteBatches for sprites that use the camera and those that don’t, which I’ve heard is very inefficient. How should I go about implementing a camera efficiently and simply? Any help is appreciated! :slight_smile:

I don’t remember the exact tutorial I used when I started to learn XNA/MonoGame, but I stumbled upon this:
http://blog.roboblob.com/2013/07/27/solving-resolution-independent-rendering-and-2d-camera-using-monogame/comment-page-1/

The way Camera/Resolution Independence works is that you use it in SpriteBatch.Begin as a parameter and then draw your sprites normally without giving them the offset.
If you don’t want to use additional SpriteBatch for sprites that don’t use camera (UI?) you can draw you just give Camera’s position as offset: SpriteBatch.Draw(Texture, Position + Camera.Position, Color.White)

Don’t worry about using few SpriteBatches, even mobile devices can handle more than one :slight_smile:

1 Like

Thanks :slight_smile: That link seems really useful, and I’ll be sure to try out some of the stuff you suggested. :smiley:

Note that SpriteBatch doesn’t necessarily even batch all Draw calls in between a Begin/End call. It can only batch sprites that use the same texture. So Begin/Draw(tex1)/Draw(tex2)/End is about as performant as Begin/Draw(tex1)/End/Begin/Draw(tex2)/End anyway. That’s why you want to use texture atlases.

But like @DedruPooru said, it doesn’t matter that much, especially if you’re only gonna have 2 batches, one for game world and one for UI.

Ok, thanks! Just out of curiosity, is it possible to do this:
spritebatch1.begin();
spritebatch2.begin();
spritebatch1.draw(stuff);
spritebatch2.draw(stuff);
spritebatch1.end();
spritebatch2.end();
or can you only start another spritebatch once all other spritebatches have ended? Thanks!

That’s possible. The SpriteBatch begin and draw calls don’t actually render things yet unless you pass SpriteSortMode.Immediate to the Begin call (but then nothing gets batched so it’s almost never what you want). They just build up a list of SpriteBatchItem (an internal class). When you call End, the graphics state (blend state, depth state…) is set, the SpriteBatchItems are sorted according to the SpriteSortMode and then the sprites are actually rendered (i.e. sent to the GPU).

So in your example everything drawn by spritebatch2 would be drawn after (so on top of) everything drawn by spritebatch1.

Ok, thanks for the clarification! :smiley:

1 Like

Next time you hear yourself utter these words try to dig a little deeper into the issue. You’ll probably find that what you’ve heard is taken out of context, utterly wrong or at the very least misleading.

In this case, by digging a little deeper you’d probably end up asking yourself some of these questions:

  1. How many SpriteBatches is too many? 2, 3, 10, 50, 100?
  2. Is my other approach actually more efficient? (passing around a vector to all sprites carries a cost as well)
  3. What kind of performance do I actually need in my game? (60 fps?)
  4. Could there be any other more important things affecting the performance? (e.g using too many textures, etc?)

The actual answer can be a little complicated. There are many things that can affect rendering performance. Chances are it won’t be what you think it will.

It think it’s great that you’re thinking about efficiency vs simplicity. But (and this is my point) you should always think about simplicity first and efficiency second. Doing it the other way around will just give you a headache :head_bandage:

My advice, try the simplest thing that works and keep an eye on your frame rate. There’s a pretty good chance you’ll spend a lot less time worrying about efficiency / performance until it actually matters. Your code will be simpler and you’ll end up optimizing the right areas rather than the wrong ones.

1 Like