What is the optimal way to store a tile based world in an array?

Started by
2 comments, last by laztrezort 11 years, 7 months ago
Hey there.
For a while I've been working on a 2d tile based side scroller (Think Terraria).

I've spend a little week now reading up on game design in general, which ended up with me questioning my current methods.
Currently my world is an array of a class I call "Tile". Tile contains a lot of information, like type, collision information, and information about whether gravity affect it, and so on. My concern is, that I am wasting a lot of memory this way?
Now I have a few solutions in mind, but I can't decide which one would be the best, or if I even need to change anything at all.
The first one would be to simply have an array of integers where each number represents a certain tile type. My concern with this method is that for every cycle I will spend a lot of cpu power instead, since I will need to do hundreds of switch cases every cycle, to determine the behavior, and what to draw everytime a number is encountered in the array.
My second solution would be a more object oriented approach, by creating a base class for the tiles, and each tile type then inherrits from that class. This way only the tiles that require special variables and methods, will get those, wile the more simple tiles will require much less memory.
If the second solution is the better one, is it then viable to check for the tile type simply by using the is statement.
An example:

if(world[x,y] is DirtTile)
{
//Draw DirtTile (or whatever :) )
}


Is that a wrong way of doing it? Or should I keep some kind of identifier in the class? - Currently I have an enumerator that holds the tile type.

Thank you for reading, and I look forward to any input smile.png

Check out the game I am making here - http://www.youtube.com/user/NasarethMekuri

Advertisement
What I have done in the past, is store an identifier in each cell, which can be used to lookup data about that terrain type from a database of terrain types. Then use the terrain data to draw, check movement, or whatever else.

Something like this (pseudocode):


class Tile
{
int TerrainIndex;
...
}
...
class TerrainType
{
Image image;
bool IsWalkable;
...
}
...
List<TerrainType> TerrainTypes...
...
DrawTile(Cell cell)
{
Image img = TerrainTypes[cell.TerrainIndex];
Renderer.DrawImage(img);
}


Thinking of cells as "just data" in this way should eliminate the need for switch cases or messy inheritance. This also allows you to keep the terrain data separate from implentation, say in a text file, that can be tweaked outside of diving through layers of code.

Differentiate between "static" and "dynamic" data. Static data can go in the database, it will not change on a per-cell basis. Dynamic data (state) can change from cell to cell, thus needs to be stored for each cell. Example of possible static data: movement blocking, sprite image, flags such as causes_damage or is_transparent, etc. Examples of possible dynamic data: per cell light level, damage level, etc. There is no hard rule for which belongs where - it depends on the gameplay, how the rendering is set up, etc.

What I have done in the past, is store an identifier in each cell, which can be used to lookup data about that terrain type from a database of terrain types. Then use the terrain data to draw, check movement, or whatever else.

Something like this (pseudocode):


class Tile
{
int TerrainIndex;
...
}
...
class TerrainType
{
Image image;
bool IsWalkable;
...
}
...
List<TerrainType> TerrainTypes...
...
DrawTile(Cell cell)
{
Image img = TerrainTypes[cell.TerrainIndex];
Renderer.DrawImage(img);
}


Thinking of cells as "just data" in this way should eliminate the need for switch cases or messy inheritance. This also allows you to keep the terrain data separate from implentation, say in a text file, that can be tweaked outside of diving through layers of code.

Differentiate between "static" and "dynamic" data. Static data can go in the database, it will not change on a per-cell basis. Dynamic data (state) can change from cell to cell, thus needs to be stored for each cell. Example of possible static data: movement blocking, sprite image, flags such as causes_damage or is_transparent, etc. Examples of possible dynamic data: per cell light level, damage level, etc. There is no hard rule for which belongs where - it depends on the gameplay, how the rendering is set up, etc.


This is an awesome Idea. I Really like it. I really look forward to cleaning up my code, and this will help me immensely.

Thank you very much for a quick and well explained answer :)

Check out the game I am making here - http://www.youtube.com/user/NasarethMekuri


Thank you very much for a quick and well explained answer smile.png


Sure, athough reading back through it I hope it made sense - I was in a hurry when I typed that out rolleyes.gif

One thing I want to clarify:


Dynamic data (state) can change from cell to cell, thus needs to be stored for each cell.
[/quote]

I should have said dynamic data (state) can change each frame, and needs to be associated with the cells in some way - the simplest way being to store the state directly in the Cell objects.

This topic is closed to new replies.

Advertisement