Reducing RAM consumption for Tile-Based map.

Started by
28 comments, last by Enokh 18 years, 9 months ago
Pictures two tile-based RPG games that have equally sized (continous [No loading]) game worlds. One game uses 42MB of RAM to store the map data. The other uses 7MB of RAM to store the map data. Both worlds are huge, 2000x2000 x 11 layers. My approach (Bad, 42MB): -> Create a giagantic linear array, and store all the data in it. Their approach (Good, 7MB): -> "We'll never tell you, buahahahah!" Loading only one layer at a time could do it, but at least 5 layers have to be loaded for multi-story buildings and mountains to be drawn. Perhaps storing the ground floor as a linear array, and the other floors as (X,Y,Tile#) structures? I'm not sure, please help! [depressed]
Advertisement
I dunno if this is better, but i know when i was experimenting with a tile engine, i used a multidimensional array, so it was like X,Y, Tile#, Flag. I used the flags to determin if it was walkable or it had treasure or something. it seemed to work out very well..dunno how much ram it took up thou...
There are a few options here. One is using metatiles, which if your maps have repetitive tile data can cut down on the space you use by a huge amount. If you use a 2x2 metatile system, you would replace your original map with one that was (width/2)x(height/2) instead. Right there you have close to a 4x memory savings. Now you just need to create the metatiles. So let's say your original map which was 6x2 looks like this (tiles go from 0-9):
016901501250

Your new metatile map would be a 3x1 map, looking like this:
010

Metatile 0 would have the following information:
0150

Metatile 1 would have the following information:
6912

So as you can see, if the maps have a lot of repitition (and empty space is very repetitive), then you can get a massive space savings. You can use different metatile sizes as well, such as 4x4 or even 8x8 if you have large areas of repitition.

Edit: Also, of course they could be loading the areas that they need dynamically from disk in a seperate thread. But it's more likely they are using a metatile system.
For a meta tile system... how does that work if I have several different types of tiles?

eg... building a metatile consisting of 3x3, I'd have to have the map as a linear array of longs (Instead of characters), because....

(150 different tiles)^(3*3) = More possilbilities than can fit on a char.

Edit: Perhaps I don't understand the metatile system, brb doing a google search. xD

Double Edit: No good results off google [bawling]. My map has ALOT of areas that are just grass or water, metatiles is sounding very promising, but I need a better explanation of it, because I get confused on how it would be used when you have more than 5 different types of tiles... lol
How densly populated are the higher layers?
Doing some maths tells me that you're simply using a gigantic char array for the whole thing. I would say that both using the meta-tile approach outlined above and for all but the base layer use a collection of
struct SomeNeatoName{  short x,y;  char tile;};

that will save space assuming that <= ~1/5 of all tiles in that layer are occupied.
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats
Another approach is to treat the world as a collection of separate regions, each region having a location and size in tile coordinates, and each having a rectangular array of tiles.

Your base would be one big region and floors of buildings would be smaller regions stacked on top. Some simple maths would allow you to work out which region the player would be in at any given time. You wouldn't have to worry about tiles that are of different sizes either.

For instance, say your world is 100x100 tiles in size, and 10 tiles high. Most everything is at ground level, but you have one building starting at tile 50,50 that is 10x10 tiles square and 5 tiles high. Here's how you could define this:

Region 1: (main world)
x,y = 0,0
w,h = 100,100
Tiles[100][100]

Region 2: (building 2nd storey [first storey is in region 1] )
x,y = 50,50
w,h = 10,10
Tiles[10][10]

Region 3: (building 3rd storey)
x,y = 50,50
w,h = 10,10
Tiles[10][10]

etc.

Hopefully you get the idea. The naive approach would be to create ten 100x100 arrays to hold the tiles, which would require storage for 100,000 tiles. The above approach would use a one 100x100 array and four 10x10 arrays, for a storage requirement of 10,400 tiles.
Yes, I'd go for the "blocks" approach. Have a 2d array of "blocks", then have each block contain a 100x100 tilemap or something.

If a given block is *entirely* empty, you can just omit it, putting a null in there or something. That means that those areas won't get stored at all.

Likewise, you could, in principle, dynamically load / save blocks of the tilemap, but that may prove unnecessary if your map is sufficiently sparse.

Mark
Ýeah, I'd say storing objects such as buildings etc. in a separate list sounds like a good idea. Also, you shouldn't have five layers just for multi-story buildings, I'd try to find a different way to do that if I were you. 11 Layers sounds pretty insane to me, at least.
It's late, so I admit that this may be a realy bad idea, but:

Could you use a quadtree to store rectangles with the same tile(s) in them, where each child node could override whatever the current tile setting is?

It seems like that would be an efficient way to store your data and still have something that's easy/fast to render. One problem I can think of is that it might be tricky to write an algorithm that automatically creates or optimizes the tree for you in your level editor...

If you have a bunch of prefabricated (That is, common building designs are cloned all over the place), you might want to just make a big list of those common pieces and have your map only store those. A *LOT* of games, both old and new, 2D and 3D use this technique. Remember the original Lemmings game? Their levels were made out of pure prefabs (at least on disc). I didn't figure out if they expanded all of those out into a big pixel grid when the level loaded, or figured out what sections you borrowed through in a big diff table or what.
I second the quadtree approach since it's basicly just a top-down approach for doing what have been suggested thus far in terms of using blocks.
HardDrop - hard link shell extension."Tread softly because you tread on my dreams" - Yeats

This topic is closed to new replies.

Advertisement