0

I am trying to program classical snake game. I have logic working (eating, growing moving etc.). Now I want to add some nice graphics. So far I have some ugly graphics i made with this code: (pseudocode)

void drawWorld(const std::vector<Tileable*> world_map) {
    for each Tileable {
         get position of Tileable
         get color of Tileable
         draw rectangle at position with color
    }
}

Class Tileable represents objects on Snakes map -> apples, walls even snake itself. It stores objects position, what happens when snake collides with object etc -> logic.

BUT

Woldn it be nice if Apples were circles, not rectangles?

So I want to add with class Drawable with method .draw() and derived classes DrawableSnake, DrawableApple, DrawableWall, DrawableWhatever, each having its own draw() method. The problem is converting Tielable subclasses from collection world_map to apropriate subclass of Drawable, to have something like this:

void drawWorld(const std::vector<Tileable*> world_map) {
    for each Tileable {
         get drawable from tileable
         drawable.draw()
    }
}

I am thinking about using something like factory with RTTI: (pseudocode)

Drawable convertToDrawable(Tileable* tileable){
     if tileable is Apple return DrawableApple
     if tileable is Wall return DrawableWall
     etc.
}

Is there some nicer way to do this, without using RTTI?

roslav
  • 470
  • 3
  • 15
  • I wan to have Tileable with children Apple, Wall, etc, and than separate hierarchy of Drawable: DrawableApple, DrawableWall,... – roslav Aug 20 '12 at 20:56
  • You probably want Tileable to have a Drawable, but I'm not sure what you're aiming for. You don't want to use RTTI for this, however. – Collin Dauphinee Aug 20 '12 at 22:45

1 Answers1

2

This is a common problem in designing game engines. One way to solve this is to move to an entity-component based system.

The apples, walls and the snake would all be of the same class - 'Entity'. To each entity you would attach a list of components. In your case 'ComponentDrawable' could be a component and 'ComponentTileable' could be another. When you create the entity you initialize ComponentDrawable with the data it needs to draw that specific entity.

You need a way to get a component of a certain type from the entity. A simple system could have each entity having an array of component pointers. Each component type would have a unique index in that array. An empty slot in the array would have a NULL value.

template<typename T> T* getComponent( Entity *entity ) {
    entity.component_array[T::index]
}

And your modified pseudocode example would then end up looking something like this:

void drawWorld(const std::vector<Entity*> world_map) {
    for each entity in world_map {
         ComponentDrawable *drawable = getComponent<ComponentDrawable>( entity )
         if( drawable )
             drawable->draw()
    }
}

Some people like to keep functionality out of the components and only use them as carriers of data. If you would like to go that route then a data driven system could use the data from the ComponentDrawable to draw the correct representation of each entity.

Jens Agby
  • 410
  • 2
  • 9