6
\$\begingroup\$

I am developing isometric 2D exploration game. At this moment I faced with a problem where game takes too much disk space. Game's world at this moment is about 1 square kilometer and it's about 50MB.

I need to somehow squeeze it. Should I think about compressing it to archive or maybe there's some kind of game files packing technique?

What about binary? Can someone explain me the magic behind it? I heard that a lot of people use it, but when I tried to use it - it took same amount of space like simple .txt file.

I'm new on file formats, so I would be grateful for any ideas. Thanks.

\$\endgroup\$
13
  • 2
    \$\begingroup\$ What kind of data are you storing for your tiles now and in what format? If it's something like XML you're using too much space. Please give more details on your current method if you want suggestions for improvements, otherwise you'll have people suggesting things that aren't compatible with what you have, or things you already have. \$\endgroup\$
    – House
    Jun 5, 2013 at 15:52
  • 2
    \$\begingroup\$ Without more information about the kind of data on disk, it's going to be hard to give you any advice about how to shrink things down other than the generic "compression" one. And is 50 megs too big really? \$\endgroup\$
    – Tetrad
    Jun 5, 2013 at 15:53
  • \$\begingroup\$ Oh, sorry. My world chunk file's line looks like this: {xCoordinates yCoordinates xChunkCoordinates yChunkCoordinates TextureId isWalkable} \$\endgroup\$
    – Tom
    Jun 5, 2013 at 15:56
  • \$\begingroup\$ I calculated that with such file format 10x10 kilometers would take about 3GB. That's really too much. \$\endgroup\$
    – Tom
    Jun 5, 2013 at 16:07
  • 2
    \$\begingroup\$ Can you provide an example entry? \$\endgroup\$ Jun 5, 2013 at 16:16

2 Answers 2

8
\$\begingroup\$

Use the organization of the data to your benefit. You can always be expect the data in the same order, so you know what the next bytes belong to. For example (not specific to your data), when reading in the data, always expect two bytes for tile type, two bytes for lighting information and then two bytes for extra info. So it knows that after 6 bytes, it's time to move onto the next tile. Don't store strings for your tile types, with two bytes you have many thousands of different types. It can take two bytes just to store one character depending on the format.

Don't store position information, it should be implied in the tile order. Always store the tile information in chunks, one column at a time (or one row at a time). This allows you to know the position of the next tile, without needing to read it from the byte stream. You read the starting position of the chunk, then the first tile is placed at that position. Then you know the second tile will be placed at the chunk position plus one in the Y direction (if sending column per column).

If your goal is to make the file smaller, you are probably going to have to give up the human readable feature (which is what your current formatting looks like it was designed for).

As for defining tiles as numbers. You just create a "conversion chart" in your code:

Decimal : Name     : Byte Value
0       : None     : 0000 0000
1       : Dirt     : 0000 0001
2       : Grass    : 0000 0010
3       : Snow     : 0000 0011
...
230     : Lava     : 1110 0110

If you have less than 256 different types of tiles (dirt, grass, sand, etc.), which is likely, you should just write a single byte to store the value of the tile.

When you write the data, make you're writing in a binary format. If you're writing characters as numbers, you're not doing it right. When you read the data back in, you check the byte value against your chart, and load the appropriate tile in to the game.

Look into how your language of choice can write to a byte stream, or write bytes directly. It's clear that you're writing text to your file because you have new lines for each tile. A binary format is probably going to be unreadable for your average text file editor. But your game can read it, so it doesn't matter.

\$\endgroup\$
15
  • \$\begingroup\$ How can you have many thousands of different types with only two bytes? \$\endgroup\$
    – Tom
    Jun 5, 2013 at 16:31
  • 3
    \$\begingroup\$ Each type is represented by a number. Two bytes can represent the numbers 0 to 65,535. One number for each type means many thousands of types. \$\endgroup\$
    – House
    Jun 5, 2013 at 16:34
  • \$\begingroup\$ I wrote 2 numbers into my .txt file and it takes 2 bytes already. How can 2 bytes represent the number from 0 to 65,535? I think I don't understand something about bytes. \$\endgroup\$
    – Tom
    Jun 5, 2013 at 16:54
  • \$\begingroup\$ @Tom 1 byte is 8 bits which can represent 256 values, so 2 bytes can represent 256*256 values, which is 65,536 values, 0-65,535 \$\endgroup\$ Jun 5, 2013 at 17:01
  • 2
    \$\begingroup\$ @Tom you aren't storing numbers in your text file, you're storing numbers represented by characters. A single character is a single byte. And the character '1' doesn't actually have the integer value of 1. \$\endgroup\$ Jun 5, 2013 at 17:22
4
\$\begingroup\$

What Byte56 says makes sense.

I'm not sure why you need 2 separate coordinates (chunk coords and xy coords). But since a map is always square, the most basic representation is a 2D array of ascii chars

..,,.....@
..,,@@@@@@
...,,,...@
......,..@

So there is the specification of a 4x10 map in 40 bytes. A 10,000 x 10,000 map would take 95MB, which isn't that bad. Because of the repetition, simple compression using zlib would probably reduce the size a lot.

To make this work, you can merge the information of tile-type and walkability together. So @ is an impassible tree, for example, and . is (passable) grass, and , is (passable) dirt. The world space coordinates of each tile is implied, as each "chunk" here is a fixed size (say 1 world unit x 1 world unit). The bottom left corner of the world could be placed at 0,0.

Using single characters means each tile can represent one of 255 different things. If you want 65,536 different things represented, you could use unicode. If you want more, you could use UTF-32.

To add in items, and NPC's you could use an item layer.

.......$$.
..t.......
....W.....
..........

Where . means empty and $ means money.

You probably could store the map size and some kind of "key" as to what each character means in the header of this map file format.

\$\endgroup\$
1
  • \$\begingroup\$ Thanks. I will try to implement your idea in some cases. \$\endgroup\$
    – Tom
    Jun 5, 2013 at 16:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .