SammygoodTunes / Tile-Game

A tile-based multiplayer game with procedural terrain generation (using the Perlin Noise algorithm)
MIT License
1 stars 0 forks source link

Decrease bandwidth by compressing map data further #11

Closed SammygoodTunes closed 2 weeks ago

SammygoodTunes commented 2 weeks ago

The map data was previously compressed into a byte object, in which each tile was stored as 4 bytes. However, the current map data being sent to (on server join) and from (all the time) the server is currently represented as such:


[map_width,map_height,tile_data,dynatile_data]

where tile_data is:

[bbbb,bbbb,bbbb,bbbb,bbbb,bbbb, ...]

b being a byte, and bbbb being a word of 4 bytes allocated for each tile

and where dyna_tile is:

[b,b,b,b,b,b,b, ...]

b being a byte allocated for the state of 8 dynamic tiles (1 bit for each tile state (0=Tile intact; 1=Tile broken)).


However, this data has a problem. It stores all tiles, even adjacent ones of identical properties. This automatically opens the possibility to reduce these adjacent duplicates, by organising the map data in a way that a specific tile is stored, then the amount of duplicate tiles that follow.

For instance, let's take the map data:

[Tiles.GRASS, Tiles.GRASS, Tiles.GRASS, Tiles.SAND, Tiles.SAND, Tiles.WATER, Tiles.WATER, Tiles.WATER] (Count: 8 elements)

With the current compression algorithm, tile_data would possess a size of 4 * 8 = 32 bytes.

If we use the aforementioned new compression algorithm, we would get map data organised in this manner:

[Tiles.GRASS, 0x3, Tiles.SAND, 0x2, Tiles.WATER, 0x3] (Count: 6 elements)

If we were to allocate the same memory for the tiles and 2 bytes (2 * 16 = 65536 > 192 192 = 36864 (max num possible tiles)) for the amount of duplicate tiles, tile_data would then possess a size of (4 + 2) * 3 = 18 bytes (=47.75% decrease)

Naturally, the simpler the terrain, the smaller the size of tile_data. But, the difference is quite noticeable.

This compression method should be applied to both tile_data and dynatile_data.

SammygoodTunes commented 2 weeks ago

Tile data done. Dynatile data needs doing maybe?

SammygoodTunes commented 2 weeks ago

Dynatile data done.

Possible amelioration: Send whole map data to client first - then for game state requests, only send breakable tile data as they are the only things to change. Or perhaps, only send dynatile data instead?

So leave tile data (+ dynatile data) for when the player joins the server, but then only dynatile_data whilst the player is connected (and requests server game state updates).

SammygoodTunes commented 2 weeks ago

Tile data is now only sent upon client authentication, while dynatile data is sent all the time.

Results:


For a 192x192 map using the default world theme:

BEFORE: ~1600 KB/min (average data received) AFTER: ~140 KB/min (average data received)