Thread: Inheritance question

  1. #1
    Registered User
    Join Date
    Nov 2008
    Posts
    2

    Question 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.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    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.

  3. #3
    Registered User
    Join Date
    Nov 2008
    Posts
    2
    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?

  4. #4
    Registered User
    Join Date
    Nov 2005
    Posts
    673
    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.

  5. #5
    Confused Magos's Avatar
    Join Date
    Sep 2001
    Location
    Sweden
    Posts
    3,145
    MagosX.com

    Give a man a fish and you feed him for a day.
    Teach a man to fish and you feed him for a lifetime.

  6. #6
    Registered User
    Join Date
    Jan 2007
    Posts
    330
    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

  7. #7
    Registered User
    Join Date
    Nov 2005
    Posts
    673
    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.

  8. #8
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    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);
    Last edited by abachler; 11-05-2008 at 04:29 PM.

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Why not use a vector (or vector of vector) instead of nasty pointer-to-pointers?
    Last edited by Elysia; 11-06-2008 at 05:43 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    why woudl you use a vector of vectors, when you need is an array of class pointers?

  11. #11
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Elysia View Post
    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.

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Actually, I did mean a vector or vector of vector.
    So vector<T*> would work as well.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Elysia View Post
    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.

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    No, I did not.
    I meant either
    vector
    OR
    vector of vector
    Two different things, depending on what you want to do.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by grumpy View Post
    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*>>.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Noob question about templates & inheritance
    By blacknail in forum C++ Programming
    Replies: 9
    Last Post: 10-25-2008, 01:51 PM
  2. Virtual inheritance
    By 6tr6tr in forum C++ Programming
    Replies: 13
    Last Post: 05-07-2008, 11:20 AM
  3. opengl DC question
    By SAMSAM in forum Game Programming
    Replies: 6
    Last Post: 02-26-2003, 09:22 PM
  4. Inheritance vs Composition
    By Panopticon in forum C++ Programming
    Replies: 11
    Last Post: 01-20-2003, 04:41 AM
  5. Very simple question, problem in my Code.
    By Vber in forum C Programming
    Replies: 7
    Last Post: 11-16-2002, 03:57 PM