Program Design Theory - Managing How To Draw To Screen

Started by
5 comments, last by chbrules 11 years, 5 months ago
So I'm writing a little 2D game for fun in C++ with the SFML API. You don't need to know about it anymore than this fact: to draw a sprite to the screen you have to pass it to the draw member method of the base window class you create. I just called it "App." So basically you go "App.draw(sprite);".

My problem comes to the design of the whole shabang. What I've ended up doing is simply passing a reference to "App" in the constructor of all the drawable objects. Every drawable/animated object has a draw member method (inherited from base class), so I just let it handle all the drawing itself in one convenient function I iterate through in a manager class using a pointer array of the base class.

Maybe I'm just crazy, but I feel this is rather sloppy. Does anyone have any input on this? Am I being an idiot doing it this way? Thanks! biggrin.png
-Conrad
Advertisement
That's a classic!

Pretend that we're writing a nice, modular piece of software. The lead announces that by the next baseline,
the near-graphics core of the code follows open for extensions / closed for modifications -principle.
(http://en.wikipedia.org/wiki/Open/closed_principle)
Now the App(the near-graphics core) cannot be modified although you want support for new sprites. Ouch!
- What went wrong?

See, if the "canvas" needs to know how to draw everything, the drawing code will easily bloat that code module / class.
If the individual drawable classes know how to draw themselves, given a bit of render context information, it makes the process extensible.
You can do this by implementing a "drawable/renderable" interface, a delegate or inheriting from a renderable base class
(depending on your language)

Hope this helps - Good luck with your project! :)
You can also use render lists, in this way a game object doesn't need to know how to render to screen, it just needs to know what of its data needs to be rendered. This is then collated in a list and that list is then used by the renderer to issue render commands.

The benefit of this is that you can do some sorting on the render list before rendering without having to sort the scenegraph or other hierarchy in which you store your renderable data.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion


You can also use render lists, in this way a game object doesn't need to know how to render to screen, it just needs to know what of its data needs to be rendered. This is then collated in a list and that list is then used by the renderer to issue render commands.

The benefit of this is that you can do some sorting on the render list before rendering without having to sort the scenegraph or other hierarchy in which you store your renderable data.


Great idea! Is there an example of this setup you could point me to? I learn well by example :]
-Conrad
Practically speaking, I think what the OP is doing seems totally fine for a small game.

If you want to do a more complicated design for the sake of learning, I'd probably look into separating the game object logic from the presentation, so you could e.g. swap your sprite rendering into a dummy ASCII rendering without having to touch the game objects.

I'm personally interested in implementing a component-based game model, but it's not a magic bullet either. For instance, if you have a game logic object with complex state, it seems like an inherently messy problem how to convey another component sufficient information to render it in the presence of animations, etc.
You can also have your drawble classes inherit from sf::Sprite class. So, you're actual class is a sprite, and you can pass it to the App.Draw, like this:

class Drawable : public sf::Sprite
{
Drawable::Drawable(sf::Image sfImage, ...) :
sf::Sprite(sfImage)
{
//.. other constructor stuff
}
};

// list that holds eveyrthing thta can be drawn
std::vector<Drawable> DrawableList;

// called from in main loop
void DrawObjects(sf::RenderWindow &App)
{
for (int i = 0; i < DrawableList.size(); ++i) {
App.Draw(DrawableList);
}
}


You get the general idea. Of course, if your drawable handle animation, then it can't be a single sprite, but this is just another option you could choose.

Good luck!

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

Thanks for the info! You guys have given me some things to think about.
-Conrad

This topic is closed to new replies.

Advertisement