Hey there, I've been trying for quite a while now to recreate the rendering system of the game called 'tibia'. It's a 2D grid-based game which consists of several 'height levels' each of those levels gets rendered on its own respectable layer, and there's a total of 14 layers, which are split into 2 sections, the underground layers (0 - 6) and overworld layers (7 - 13), which means that only 7 layers get rendered at a time. I've recreated the actual rendering but it's more or less a brute force approach and the FPS drops quite a lot as more layers are turned into a render. I'm using GMS2 which has pretty poor optimization (starting from the variables themselves, almost everything is declared as an int64 even 'booleans'). This is what I've done so far:
First of all, I'm saving all the map data inside of a buffer (buffer size is map_width * map_height * floors(12) * 4 BYTES). The first of the 4 BYTES is split into three groups [00][00][0000] respectively where the first group holds the multiplier of the sprite_data for the GROUND (terrain) the second group holds the multiplier for the TRANSITION(e.g. water -> grass, grass -> dirt) and the third group has 15 possible combinations which would hold Monsters/Npcs/Objects. Now then, the second BYTE holds the ID of the GROUND floor inside the spritesheet. There's a total of 255 combinations * 4 (the multiplier from the first BYTE), the third BYTE and fourth BYTE basically represent the same thing with different data(TRANSITIONS and OBJECTS). I've also created another buffer which holds the collision_map data, basically it's a map_width*map_height*floors*1BIT and it's a 1 or a 0 per tile.
Now then here comes the problematic part, the rendering itself. Basically when the game starts everything gets rendered first time via brute force
for(z=0 z<ground_floors; z++)
for(i=0; i<width; i++)
for(j=0;j<height;j++)
draw_tile(x,y,tile_sprite);
When the camera moves(or the player if you will) depending on the direction I'm rendering only the row/column which is being revealed as he moves on, but the thing is I'm rendering it 6 times (because there are 6 floors). I've realized that I might render from top to bottom, and do something like:
for(z=max_floor; z>6; z--){
for(i=0; i<row_size; i++){
if(tile(z) != 0)
draw_tile(x,y,tile_sprite);
else break;
}
}
Which would save quite a lot of calculations but only if there are tiles on higher floors, otherwise it would result in a drawing of floor_count * row_size calls. I've also been considering about checking if I'm currently at a floor which is greater or lower than ground_floors/2 and based on that I'd render either from the bottom up or from the top-down but I'd probably still have a lot of issues while drawing. My actual problem is that my FPS drops quite a lot when drawing on the last 2 top-most floors, for example it's something like 240 FPS on the lowest floor, while it's 35-40 FPS at the top-most floor.
I hope that you can understand my gibberish code.
Thanks in advance,
Alex