5
\$\begingroup\$

Suppose I have a SquareObject class, which implements IDrawable, an interface which contains the method void Draw(). I want to separate drawing logic itself from the game core engine.

My main idea is to create a static class which is responsible to dispatch actions to the graphic engine.

public static class DrawDispatcher<T>
{
    private static Action<T> DrawAction = new Action<T>((ObjectToDraw)=>{});
    public static void SetDrawAction(Action<T> action)
    {
        DrawAction = action;
    }
    public static void Dispatch(this T Obj)
    {
        DrawAction(Obj);
    }
}

public static class Extensions
{
    public static void DispatchDraw<T>(this object Obj)
    {
        DrawDispatcher<T>.DispatchDraw((T)Obj);
    }
}

Then, on the core side:

public class SquareObject: GameObject, IDrawable
{
    #region Interface
    public void Draw()
    {
        this.DispatchDraw<SquareObject>();
    }
    #endregion
}

And on the graphics side:

public static class SquareRender{
    //stuff here
    public static void Initialize(){
        DrawDispatcher<SquareObject>.SetDrawAction((Square)=>{//my square rendering logic});
    }
}

Do this "pattern" follow best practices?

And a plus, I could easily change the render scheme of each object by changing the DispatchDraw parameter, as in:

public class SuperSquareObject: GameObject, IDrawable
{
    #region Interface
    public void Draw()
    {
        this.DispatchDraw<SquareObject>();
    }
    #endregion
}
public class RedSquareObject: GameObject, IDrawable
{
    #region Interface
    public void Draw()
    {
        this.DispatchDraw<RedSquareObject>();
    }
    #endregion
}

RedSquareObject would have its own render method, but SuperSquareObject would render as a normal SquareObject

I'm just asking because i do not want to reinvent the wheel, and there may be a design pattern similar (and better) to this that I may be not acknowledged of.

Thanks in advance!

\$\endgroup\$

3 Answers 3

5
\$\begingroup\$

I don't think dispatching events is the best way to do this. If you have a high amount of draw calls the event dispatching and listeners will have a lot of overhead.

Also you might want to look what classes you have, because you don't need a class for each color of square, or even if there are more properties. You could be able to just store the color or other information in a variables on each instance instead of having a lot of classes for really similar objects.

For the drawing, you can just set up either a static or non static function in the class that has the Update. So you will have an Update() and a Draw() method in one class. In the main game's Update method, call the Update() method on the instance(s) that need to be updated. Depending on your logic, if there is enough time left over, you then call the Draw() method.

Make sure that the game doesn't require the Draw() method to run exactly at your refresh rate. If the game cannot keep up, it is best to skip Drawing for that frame, so the game will have more time to run the next step in the simulation.

\$\endgroup\$
2
  • \$\begingroup\$ But then, when I want to change how something is drawn, I'll have to create another class for that, won't I? This way I could have specific classes to "skin" my own game, just setting the drawaction to something else (like drawing a border on every game object). I dunno. \$\endgroup\$ Commented Mar 20, 2011 at 13:29
  • \$\begingroup\$ No just have a field in each object that holds information that references what graphics it has. Don't store the actual graphic in each object. Use an Asset Manager. \$\endgroup\$ Commented Mar 20, 2011 at 18:12
6
\$\begingroup\$

The best practice for separating the game logic from game rendering is to have separate objects for the logic and the renderable, instead of having one large object that performs both tasks. The renderable object has a reference to the logic object so that it can update its own state (eg. animations) based on data in the game logic, or just query for relevant properties directly (eg. current position).

Once you make that separation, most of these issues above disappear, and you don't have to worry about complicated observer patterns or event dispatch.

\$\endgroup\$
3
  • \$\begingroup\$ Why would the renderer update the objects positions? Surely that should lie with the animation and physics layer. Which may abstract from a movable layer... and so on \$\endgroup\$ Commented Apr 1, 2011 at 5:16
  • \$\begingroup\$ My wording was unclear - I meant the renderable can update its own state, based on the game logic. I'll edit the answer to make this clearer! \$\endgroup\$
    – Kylotan
    Commented Apr 1, 2011 at 11:04
  • \$\begingroup\$ This is the same pattern used in modern GUIs like WPF, which have a logical tree (Button, List, ...) and a visual tree (Border, Ellipse, Bitmap, ...) \$\endgroup\$
    – Meh
    Commented Apr 2, 2011 at 20:05
1
\$\begingroup\$

We use a component class with optional interfaces for IUpdatable and IRenderable that tie into the scene container which handles the component life cycle (when the game engine core says "time to render", the scene container updates all the updatable components, then renders all the renderables). Since we construct lists of updatable and renderable components every time the scene graph changes... dispatching the update and render calls is very simple -- a couple of for each loops... we even sort the renderables based on the material/shader so that we can eliminate some rendering calls related to setting up the shader state when we are using the same shader over and over (simple shader batching)

\$\endgroup\$

You must log in to answer this question.

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