3
\$\begingroup\$

I'm currently making a 2D Worm-clone in XNA, and have regrets about the way I've made my camera. I declare my camera in my Main class and the camera follows the player. In my draw I then begin my spritebatch using my camera transformations.

The problem is, EVERYTHING needs to be drawn in Main because they need to be drawn under the camera transformations (unless I send the camera to each classes constructor).

My question is, is there a way to make it so the Camera is basically global over my whole program, everything is "by default" affected by it? Or at least so it's not only in Main and I can have things that draw themselves.

I've searched for tutorials, but they all explain how to make the camera and to implement it in one draw function, not over a whole program with many different entities.

\$\endgroup\$

3 Answers 3

3
\$\begingroup\$

I'm afraid I have to disagree with Andrew on this one. I do recommend the DrawableGameComponent architecture and I would dispute that this, or the services pattern, are particularly 'heavyweight' - I do have other issues, outside of the scope of this question, but performance generally isn't one of them.

Creating a single camera object to provide a view and projection matrix to your drawables is straightforward and allows you to have your objects draw themselves in their own Draw method. This is, by far, the most common way of structuring an XNA project in my experience. At the end of the day your drawables are only maintaining a reference to a single object, so there is not much overhead.

How you provide this reference is a matter of taste and whether you are bothered about reusing your code in other projects:

  • You can offer the camera through the services pattern and get hold of it in your drawable's Initialize method.
  • Pass it in during construction (provided it has already been instansiated).
  • Use a public Property of your derived game class (which you retrieve by casting the Drawable's game object reference to the derived game type first)
  • Use a Static, as Andrew suggests.

Personally I would suggest one of the first 2 options (via an ICamera interface definition) to neatly decouple your actual camera & drawable implementations for later re-use. Personally I don't believe well structured code is 'fancy' - good code is just good code.

\$\endgroup\$
3
  • \$\begingroup\$ Are there any down sides to making the camera a Public Static? If not it seems that it is a lot simpler to do that than say, pass the camera in every objects constructor. To be honest, I'm quite new at XNA and Game Development in general (I've previously done a lot of Actionscript, but this is quite different), and I'm not really familiar with the services pattern you guys are talking about. If it's the best route to go though I will look it up. \$\endgroup\$
    – Benixo
    Commented Mar 30, 2011 at 18:46
  • 1
    \$\begingroup\$ Hi Ben, when you have time do look at the services pattern - I wrote this a while ago: xna-uk.net/blogs/braindump/archive/2009/08/23/… In your current project the downside of using a Static on the specific game object is that your drawables will always be 'tied' to this object in the future in order to get their camera - a service or passed standard interface will 'decouple' the drawables from any particular game object. To re-use them in the future they just need to be created in a new Game object that offers an object with this interface. \$\endgroup\$ Commented Mar 30, 2011 at 21:06
  • \$\begingroup\$ Oooooh, that makes a lot of sense actually. I was even thinking of reusing some objects in later projects. Thank you for the link too, very useful! \$\endgroup\$
    – Benixo
    Commented Mar 31, 2011 at 0:32
3
\$\begingroup\$

OK, so when you say "Main" I am imagining you mean the class that you derive from Game?

There is nothing wrong with calling SpriteBatch.Begin() multiple times around your program and passing in your camera matrix to each one.

Presumably each of your gameplay classes has a Draw method? I recommend passing either your camera matrix or a class containing your camera matrix into each Draw function you are calling. So your Draw function in your game class might look like this:

protected override void Draw(GameTime gameTime)
{
    player.Draw(spriteBatch, camera);
    foreach(var enemy in enemies)
        enemy.Draw(spriteBatch, camera);
}

If your gameplay classes are DrawableGameComponents, well this is a really good reason not to use game components!

Of course, if you insist on using DGC, then passing a camera class to each constructor, as you mention, will work. But as you've probably discovered, it means you have to figure out how to store it in each class - along with quite a bit of code duplication to do so.

You could also use the Services architecture to allow your components to access the camera. But like DGC, this is a very "heavy" architecture. Why write and manage a service, when you can just make your camera global by making it a public static member of your game class?

(It's gameplay code. It doesn't have to be fancy. DTSTTCPW.)

\$\endgroup\$
0
\$\begingroup\$

You need to create your own Camera "engine". It isn't good to put your camera on Main and force to draw all the entities here. And in the same way, it isn't a good idea to draw everything in the same class. For this reason, you can to create your Camera as an entity or class. This Camera has to be accesible to the rest of the game (static) Draw the object in their own classes (not in main, each object draw itself (or in your render engine class it has)) and when you draw it, call to camera to apply the transformation. Example: public Draw(GameTime gameTime) ... Matrix transform = Game.CameraEngine.Get.... spriteBatch.Begin(...,transform). ....

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .