# Inheritance question

Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last
• 11-04-2008
alexy
Inheritance question
Hello, I have written a map generator for a game and I read in some book that inheritance should be right way to get away from the switch statement. So I write something like this:

Code:

```class Tile {...}; /* Abstract base class */ class X: public Tile {...}; class Y: public Tile {...};```
Then I have map:

Code:

`Tile* map[W][H];`
So when I draw it on the screen I do something like that:
Code:

`for (i=0;...) for (j=0;...) map[i][j]->draw();`
Looks like good runaway from switch statement, but when I generate that map I do it iterative way: first i set every tile to ocean, then randomly generate island, on island I place mountains, near mountains I place forests and so forth.

So I generate another array of integer numbers, generate map on it and convert them to Tile descendants. And it is made with huge switch statement. Can you point me some way to escape this last switch? Can OOP and inheritance be useful here?

English is not my first language. Sorry for mistakes.
• 11-04-2008
tabstop
Do you not have Tile descendants for Ocean, Island, Mountain, Forest, whatever else? Each of your map[i][j] should be of different classes, and each draw() function should know how to draw whatever class it's a part of.
• 11-04-2008
alexy
Yes, but when I generate map I do this (very simplified):

Code:

```enum { intOcean=0, intLand, intMountain }; void generate() { // make ocean for (i=0;...) for (j=0;...) intMap[i][j]=intOcean; } // make land: intMap[W/2][H/2]=intLand; // Add more land: for (k=0;k<MAX_LAND;k++) { for (i=1;...) for (j=1;...) if (intMap[i][j]==intOcean && (intMap[i-1][j]==intLand||intMap[i+1][j]==intLand...)) { intMap[i][j]=intLand;} } // Add mountains: for (k=0;k<MAX_MOUNTAINS;k++) {...} // Add something else.... ... }```
and then I got huge switch:

Code:

```for (i=0;...) for (j=0;...) { switch(intMap[i][j]) { case intOcean: map[i][j]=new Ocean; break; case intLand: map[i][j]=new Land; break; .... } }```
So I want to know: this code utilises a procedural approach to generate map. Can it be done with OOP methods? Without last switch?
• 11-04-2008
Raigne
First off why have different classes for every Tile type?

If you have a single Tile class then you can allocate the entire map then assign the type(all in the same function) This would remove the need for the intMap array, and would save a lot of CPU cycles.

I see no need in different Tile classes. In my game, I have a single terrain node class, each node has its own set of flags, coordinates, etc. Then based on flags determines what can or cannot be done on that node.
• 11-05-2008
Magos
• 11-05-2008
KIBO
you will need always need a switch like construct somewhere in your code. You can hide the switch by associative arrays or whatever but it's still a switch like construct. Suppose you will make a map editor. You are probably gonna identify the tile types by numbers or strings. The code that reads the map format will have to check those identifiers and create the correct Tile instances. For that use the factory patterns from the post above.

The advantage of the OO method is that the switch occurs only once....on startup. In your example the advantage is not really clear because you have only one overridden functions (draw)

Suppose you have a Tile without inheritance and use and integer id to get to the tile type. So inside draw() you will have

Code:

`switch(Type) { case OCEAN: //etc }`
Then you add movement to your game so you add a int GetMovePenalty() to your tile (each tile type has different move penalties).
inside the function you do again:
Code:

`switch(Type) { case OCEAN: //etc }`
Then the same for every little game feature you add and you end up with 50 of those functions.
Then you decide that it would be cool to add a CRATER type of tile because a bomb fell there. You will have to go over all the 50 functions adding case CRATER to the code.
If you'd done it with subclasses you could've just created a subclass Crater and override the functions once and when a bomb falls you can do

Code:

```delete map[i][j]; map[i][j]; map[i][j] = new Crater();```
and

Code:

```map[i][j]->draw(); map[i][j]->GetMovePenalty()```
will automatically change
• 11-05-2008
Raigne
Why would draw need to know the type of tile? Draw should draw the map and nothing else. It should not need to check for Tiletype. It should loop through an array of Tiles, and draw their (texture/color/symbol, or whatever you are using to display them). The draw method should not care about what type of tile it is.
• 11-05-2008
abachler
Arbitrarily avoiding the switch statement doesnt make a lot fo sense, especially if doing so creates code bloat and obfuscation. Ultimately, you need to chose one fo several options based on a variable, and the compiler will produce similar code regardless of what method you use.

You could simply create a single tile class which takes the tile type in its constructor
Code:

``` class Tile { public:   Tile(DWORD TerrainType);     DWORD TerrainType;     void Draw(DWORD TilePosition);   };```
then have the draw member function take the screen position and draw whatever its type is. Create an array of
Code:

`Tile** MyTile = new Tile*[5];`
and instantiate each terrain type as a member of that array. You would have to flesh otu the class to include variables for the terrain graphic etc, btu once you create Tile(0), calling the draw method of that class will always draw that terrain type.

Then as you need to draw each type, instead of switch(TerrainType){} you just call MyTile[TerrainType]->Draw(Position);
• 11-06-2008
Elysia
Why not use a vector (or vector of vector) instead of nasty pointer-to-pointers?
• 11-06-2008
abachler
why woudl you use a vector of vectors, when you need is an array of class pointers?
• 11-06-2008
grumpy
Quote:

Originally Posted by Elysia
Why not use a vector (of vector) instead of nasty pointer-to-pointers?

Because he wants an array of polymorphic objects. a vector<vector<T > > does not give that, even if T is a polymorphic type.
• 11-06-2008
Elysia
Actually, I did mean a vector or vector of vector.
So vector<T*> would work as well.
• 11-06-2008
grumpy
Quote:

Originally Posted by Elysia
Actually, I did mean a vector or vector of vector.
So vector<T*> would work as well.

So you describe a vector<T *> as a "vector of vector"????

Mixing up concepts (eg describing something as being something it's not) is an effective way to cause confusion. It strikes me you are doing that.
• 11-06-2008
Elysia
No, I did not.
I meant either
vector
OR
vector of vector
Two different things, depending on what you want to do.
• 11-06-2008
tabstop
Quote:

Originally Posted by grumpy
So you describe a vector<T *> as a "vector of vector"????

Mixing up concepts (eg describing something as being something it's not) is an effective way to cause confusion. It strikes me you are doing that.

No, I believe elysia would refer to vector<T*> as "vector". The point was turning map[i][j] into vector<vector<Tile*>>.
Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last