2
\$\begingroup\$

I'm still somewhat new to "proper" design, but I'm trying to keep with it as much as possible. I thought I was OK but I've run across a slight dilemma: how should I be implementing the actual drawing and updating of entities?

For example, in my project I have a TextBox class. The 'easy' way, and the way that I usually see in tutorials across the Internet, are to give this class its own Update() and Draw() methods. But I don't think my textbox class should have to know anything about how it's being drawn, so I thought it might be good to make it implement some kind of Drawable interface, but even that still involves implementing drawing code.

So I thought of adding all my TextBoxes to a List<TextBox> that a drawing class would load to handle the drawing, but then I realized that my TextBox class itself doesn't (and shouldn't?) have a Draw() method within the class, so I would have to write a sister method in the graphics implementation somewhere as a DrawTextBox() or something like that. I guess this COULD work, but I can't shake the feeling that having to have this kind of coupling of classes is bad practice.

So where should I ultimately be placing the code to draw, and where should I have the logic behind it? A TextBox, for example, involves drawing multiple elements, and it's timed because it's a typewriter-style output, and I eventually want to add in-text commands for delays and sound. Should I include some of this stuff in the main class? Have a Draw method in some graphics class somewhere else? And then later dealing with timing and sound, how should I be separating all of it?

\$\endgroup\$

3 Answers 3

2
\$\begingroup\$

The way I've always done it is to have each object draw themselves. It keeps everything in one place, you don't need to open up the internals for someone else to draw you, and therefore can increase encapsulation. This also allows you override the draw method to do something special in derived classes.

\$\endgroup\$
3
  • \$\begingroup\$ I guess the biggest question I have is about the acceptability of doing this from a software design perspective. I know it's not that big of a deal, especially in a small thing like my project, but I'd like to do it 'right' and learn as much from it as I can. Which is why I'm wary of giving each entity its own draw code... \$\endgroup\$
    – ssb
    Feb 19, 2012 at 9:09
  • 1
    \$\begingroup\$ If it works, and you understand the code, it's acceptable. There is no 'right', just code that works and/or is maintainable, and code that isn't. \$\endgroup\$
    – Kylotan
    Feb 19, 2012 at 11:33
  • 1
    \$\begingroup\$ It's quite common to have each object draw themselves. Nobody knows, or should know more about how to draw your entity than the entity itself, textbox or otherwise. XNA's standard way is to have your game elements extend from DrawableGameComponent and override the Draw() method to draw yourself. In Windows, the controls also Paint themselves. \$\endgroup\$ Feb 19, 2012 at 17:26
1
\$\begingroup\$

I think which way you chose to organize code depends on the scale of the game and how far you are willing to go out of your way to make the program beautiful and efficient.

That said I would have a Drawing class that implements every type of object that can draw to the screen in your game. Then have an interface implement these behaviors and pass that interface to the classes that need to make draw calls on objects.

class Sprite {}
class Player {}
class Enemy {}
class Terrain {}

public class DrawingManager : IDraw {}

public interface IDraw
{
    void DrawSprite(Sprite sprite);
    void DrawPlayer(Player player);
    void DrawEnemy(Enemy enemy);
    void DrawTerrain(Terrain terrain);
}

Since your using XNA you can pass the IDraw interface using Game.Services or you can write your own helper class for that. Either way if you want to achieve a typewrite type output (display a certain amount of text per frame I assume), this would work. Just keep a copy of the object in the DrawingManager (passed through by the interface), and once it reaches the end have some to clear it from the DrawingManager's list when its done.

\$\endgroup\$
1
\$\begingroup\$

I sometimes like to have the entity keep a reference to the object that will represent it on screen, and return that to the renderer object when it's time to draw everything.

Another way would be to have separate EntityRenderer objects in a list, each holding a reference to the entity in question, and deciding how to render it based on the entity's properties. This is close to a pure separation of responsibilities but can be a lot of work for little benefit.

\$\endgroup\$

You must log in to answer this question.

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