views:

79

answers:

2

Hi

Im trying to make an 2D online game (with Z positions), and currently im working with loading a map from a txt file. I have three different map files. One contains an int for each tile saying what kind of floor there is, one saying what kind of decoration there is, and one saying what might be covering the tile. The problem is that the current map (20, 20, 30) takes 200 ms to load, and I want it to be much much bigger. I have tried to find a good solution for this and have so far come up with some ideas.

Recently I'v thought about storing all tiles in separate files, one file per tile. I'm not sure if this is a good idea (it feels wrong somehow), but it would mean that I wouldn't have to store any unneccessary tiles as "-1" in a text file and I would be able to just pick the right tile from the folder easily during run time (read the file named mapXYZ). If the tile is empty I would just be able to catch the FileNotFoundException. Could anyone tell me a reason for this being a bad solution? Other solutions I'v thought about would be to split the map into smaller parts or reading the map during startup in a BackgroundWorker.

+1  A: 

Try making a much larger map in the same format as your current one first - it may be that the 200ms is mostly just overhead of opening and initial processing of the file.

If I'm understanding your proposed solution (opening one file per X,Y or X,Y,Z coordinate of a single map), this is a bad idea for two reasons:

  • There will be significant overhead to opening so many files.
  • Catching a FileNotFoundException and eating it will be significantly slower - there is actually a lot of overhead with catching exceptions, so you shouldn't rely on them to perform application logic.
MisterZimbu
Okay, thanks:) I'll make a bigger map an try loading it in a background worker instead
Alle
I think 200ms is quite a bit of overhead just to open a small file. I suspect the file is remote...
Cam
Sorry, I saw that it was actually (50, 50, 30).
Alle
+1  A: 

Are you loading the file from a remote server? If so, that's why it's taking so long. Instead you should embed the file into the game. I'm saying this because you probably take 2-3 bytes per tile, so the file's about 30kb and 200ms sounds like a reasonable download time for that size of file (including overhead etc, and depending on your internet connection).

Regarding how to lower the filesize - there are two easy techniques I can think of that will decrease the filesize a bit:

1) If you have mostly empty squares and only some significant ones, your map is what is often referred to as 'sparse'. When storing a sparse array of data you can use a simple compression technique (formally known as 'run-length encoding') where each time you come accross empty squares, you specify how many of them there are. So for example instead of {0,0,0,0,0,0,0,0,0,0,1,1,2,3,0,0,0,0,0,0,0,0,0,0,0,0,1} you could store {10 0's, 1, 1, 2, 3, 12 0's, 1}

2) To save space, I recommend that you store everything as binary data. The exact setup of the file mainly depends on how many possible tile types there are, but this is a better solution than storing the ascii characters corresponding to the base-10 representation of the numers, separated by delimiters.


Example Binary Format

  • File is organized into segments which are 3 or 4 bytes long, as explained below.

  • First segment indicates the version of the game for which the map was created. 3 bytes long.

  • Segments 2, 3, and 4 indicate the dimensions of the map (x, y, z). 3 bytes long each.

  • The remaining segments all indicate either a tile number and is 3 bytes long with an MSB of 0. The exception to this follows.

  • If one of the tile segments is an empty tile, it is 4 bytes long with an MSB of 1, and indicates the number of empty tiles including that tile that follow.

The reason I suggest the MSB flag is so that you can distinguish between segments which are for tiles, and segments which indicate the number of empty tiles which follow that segment. For those segments I increase the length to 4 bytes (you might want to make it 5) so that you can store larger numbers of empty tiles per segment.

Cam
No, the map files are stored locally. @ 1) Thanks:) That will probably make the reading faster and take less space, since many elevations / floors in Z will be almost completely empty. @ 2) I tried to use a binary writer earlier, but I ended up with a twice as big file, but maybe I did something wrong.
Alle
@Alle: No problem. If the game is online (eg. flash/java game), how are you able to store the map files locally? Or is the entire game stored locally and it's simply a multiplayer game? Regarding binary - it will definitely cut down on the file size if you do it right. First of all do you think having up to 4095 (=3 bytes) different tiles would suffice? If so I'll edit my answer with a more detailed suggestion for the binary format :)
Cam
Oh, I noticed I wrote wrong, the file I load is actually 50,50,30 and not 20,20,30
Alle
oh, yeah, I will probably not need more than a couple of hundreds. The graphical map is stored in the client. The only thing the player get from the server regarding the map is whether the tiles around him is solid or not.
Alle
Another option would be to instead of storing each tile's data regardless of whether it's empty or not, just store the location of tiles with stuff and process them incrementally.I'm guessing with a 50x50x30 grid + slow loading time we have nested loops loading the tiles; a O(n^3) load time that won't scale well.
MisterZimbu
@MisterZimbu: That's a good idea, except the extra space required to store the coordinates (especially in 3 dimensions) makes me think it might not be worth it.
Cam
If I were to do that, I would need to write (X Y Z TileID) for each tile, right? And yeah, that won't scale well:P But at least the game will not be cubical (Z will not increase more, it will stay 30). The X and Y I hope to be able to get to as much as around 2000.
Alle
@Alle: I've added an example of how you could organize the file in a binary format. It's a combination of my two suggestions (binary format + run-length encoding for empty tiles). The binary format will decrease the filesize simply because it's more compact, and the run-length encoding will allow sparser maps to take up less space even if the map itself is enormous.
Cam
Thanks, I'll see if I can wrap my head around it:). Not that familiar with reading byte data.
Alle