I'm making a 2d tile based game, and I've tried to keep my tile structure small by using bit fields and bytes for the values in the tile structure:
struct Tile
{
// 3 bytes (24 bits)
BYTE i : 8; // Texture index (0-255)
BYTE p : 1; // Passable (0-1)
BYTE x : 7; // Texture x (0-127)
BYTE y : 7; // Texture y (0-127)
BYTE v : 1; // Visible (0-1)
};
so if i have a 2d array of 1024x1024 tiles, then its only around 3mb in memory and when i save/load from hd.
But now I need animated tiles, so I need extra data like,
struct Tile
{
#define TILE_NORMAL 0
#define TILE_ANIMATED 1
BYTE tile_type;
// 3 bytes (24 bits)
BYTE i : 8; // Texture index (0-255)
BYTE p : 1; // Passable (0-1)
BYTE x : 7; // Texture x (0-127)
BYTE y : 7; // Texture y (0-1开发者_运维百科27)
BYTE v : 1; // Visible (0-1)
// For animated tiles
BYTE frame;
BYTE maxFrame;
float frameTime;
};
On each of the tiles, and since the 2D array is defines like:
Tile tiles[x][y];
Each tile would be around 10 bytes, even though a very small proportion of the tiles are animated.
I was thinking to store a 2D array of pointers, and then each points to either a normal tile or a animated one, but that would mean every pointer is 4 bytes, and points to atleast 4-10 bytes.
If you want to save memory, don't store the animation data in the tiles themselves. Instead, you could define a separate struct in your game program, such as:
struct AnimationSequence
{
BYTE first;
BYTE current;
BYTE frames[];
float frametime;
}
Then you could define an array of a couple of these which represent each type of tile that animates, and how it animates. Then, in your animation timer, cycle through this array, check it against the tiles on the screen, and redraw them as needed.
Another thing you might want to consider, to save more memory, is not storing X/Y coordinate values in the tile data. I'm assuming your X/Y bytes represent the position the tile is drawn on the screen, or something similar. You could try attaching the coordinate values to the view window of the game in their own array, rather than to the tiles themselves, so that you would only have one view window worth of tiles to serve as a lookup list for when you are drawing them to the screen, rather than a whole map's worth.
Could you make the struct a union? For example (and please pardon any syntax errors, I don't remember the exact syntax):
struct Tile
{
#define TILE_NORMAL 0
#define TILE_ANIMATED 1
BYTE tile_type;
// 3 bytes (24 bits)
BYTE i : 8; // Texture index (0-255)
BYTE p : 1; // Passable (0-1)
BYTE v : 1; // Visible (0-1)
BYTE x : 7; // Texture x (0-127)
BYTE y : 7; // Texture y (0-127)
union
{
struct AnimatedTileData
{
// For animated tiles
BYTE frame;
BYTE maxFrame;
float frameTime;
};
struct NoData
{
};
};
};
So, in this way, you have one extra byte to say whether it is animated or not. If it is not animated, then 'NoData' will be used, added no overhead. If the tile is animated, then the 6 overhead bytes are added for animation related data.
精彩评论