Wednesday, July 27, 2016

xna - What are the cons of using DrawableGameComponent for every instance of a game object?


I've read in many places that DrawableGameComponents should be saved for things like "levels" or some kind of managers instead of using them, for example, for characters or tiles (Like this guy says here). But I don't understand why this is so. I read this post and it made a lot of sense to me, but these are the minority.



I usually wouldn't pay too much attention to things like these, but in this case I would like to know why the apparent majority believes this is not the way to go. Maybe I'm missing something.



Answer



"Game Components" were a very early part of the XNA 1.0 design. They were supposed to work like controls for WinForms. The idea was that you would be able to drag-and-drop them into your game using a GUI (kind of like the bit for adding non-visual controls, like timers, etc) and set properties on them.


So you could have components like maybe a Camera or a... FPS counter?... or...?


You see? Unfortunately this idea doesn't really work for real-world games. The kind of components you want for a game aren't really reusable. You might have a "player" component, but it will be very different to every other's game's "player" component.


I imagine it was for this reason, and for a simple lack of time, that the GUI was pulled before XNA 1.0.


But the API is still usable... Here's why you shouldn't use it:


Basically it comes down to what is easiest to write and read and debug and maintain as a game developer. Doing something like this in your loading code:


player.DrawOrder = 100;
enemy.DrawOrder = 200;


Is much less clear than simply doing this:


virtual void Draw(GameTime gameTime)
{
player.Draw();
enemy.Draw();
}

Especially when, in a real-world game, you might end up with something like this:


GraphicsDevice.Viewport = cameraOne.Viewport;

player.Draw(cameraOne, spriteBatch);
enemy.Draw(cameraOne, spriteBatch);

GraphicsDevice.Viewport = cameraTwo.Viewport;
player.Draw(cameraTwo, spriteBatch);
enemy.Draw(cameraTwo, spriteBatch);

(Admittedly you could share the camera and spriteBatch using the similar Services architecture. But that is also a bad idea for much the same reason.)


This architecture - or lack thereof - is so much more light weight and flexible!


I can easily change the draw order or add multiple viewports or add a render target effect, just by changing a few lines. To do it in the other system requires me to think about what all those components - spread across multiple files - are doing, and in what order.



It's sort of like the difference between declarative vs imperative programming. It turns out that, for game development, imperative programming is far more preferable.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...