[quote name='mike3' timestamp='1330387721' post='4917230']
2. we need to allocate on the heap with new (and that takes more time, doesn't it, than just updating a type field) if we want to change a tile
3. when changing a tile, we need to be able to preserve its flags, which means we need some kind of "copyFlags()" function or something in LevelTile that would need to be called when doing such a change and so would complicate setting one tile to that of another type, or have conversion code for each kind of tile
Change a tile? You still would NOT create an entire instance for every tile on your map. As already suggested, create a list of prototype tiles in an array with all common data (textures, etc.), make all "unique" data function parameters and there shouldn't be any overhead worth mentioning. tile[y][x]->protoTile->onSomeEvent(x, y, list_of_stuff_on_tile).
Krohm suggested an easy way, but unless you clearly define your requirements from the beginning and don't care about modding or extending, this is going to be a pain later on. Imagine having defined tons of tile types like this. Now you figure "hey, a special healing tile would be neat" or "how about a teleport tile"? You'd have to extend the struct and add a silly amount of 0s to every tile, just because ONE is special.
This is easier solved by either virtual functions in your prototype tile types or simple function pointers. The latter has the big advantage of not needing a separate class and then having only this one single instance. It might also be a lot easier to change later on to execute an external script instead (allowing to add new tile types and their behavior without having to touch the actual code itself).
In that case, when a tile is "activated" you can do something like tileInfo[tileId]->onActivated(...) (downside compared to virtual functions with empty default implementation: you will have to either check the function pointer first or always assign some empty default function yourself).
Your average tile might not even need any information other than an id or pointer to its tile info. Eventually you will probably still need some generic info field (to store state or orientation, etc.). The exact meaning of those however might be completely different for every tile. You just stuff that data into the prototypes functions and it will know what to do with it.
[/quote]
So then if I'm getting this right, you're suggesting a global(!!! argh !!!) array of tile prototypes, accessible from anywhere it's needed, and each map element is a reference to a tile prototype? But then what if we need to store information that can vary between individual map tile elements as opposed to between tile types?
And when you mention about using function pointers to make more extensibility, do you mean keeping an array of them in the thing to which new ones can be added? Like if we need that healing tile, and need to add a function for that, we can add it to that array instead of having to add a field that then needs to be filled on
all tile types (which offers no advantage to Krohm's method)?
And what do you mean by "stuff the data into the prototype functions"?
Do you mean something like this?:
class TileRepresentation {
... graphics, anim., etc. stuff ...
};
class TilePrototype {
private:
TileRepresentation *tileRep;
int intrinsicFlag1;
int intrinsicFlag2;
SomeFunctionPtrType funcPtr1;
SomeFunctionPtrType funcPtr2; // but what if we need more functions in some kinds of tiles and less in others?
public:
...
};
class MapCell {
private:
TilePrototype *proto; // points into the pre-baked list of tile prototypes
int someCellSpecificFlag1;
int someCellSpecificFlag2;
public:
...
};
class Map {
private:
std::vector< std::vector<MapCell> > mapData;
...
public:
...
};