I’ve had fun with tiled, and now I’m generating my map dynamically, and it could be huge.
So I thought I’d cut the world in chunks of 50x50 tiles, and wherever the character is, I’ll load the chunks around his.
Don’t just take my word for it, behold my amazing graphic skills :’)
So the red dot is the character. The black squares are the map chunks, and the purple area are the chunks that are loaded respectively to the position of the character.
When the character moves on a chunk on the east, I shall load the blue area, and unload the green one :
Have you tried loading the whole map? Assuming you will need to chunk the map is what developers often call “pre-emptive optimization” and is usually a bad idea because oftentimes we can spend a ton of time optimizing something that didn’t need it. Or even worse, our “optimizations” actually result in overall slower performance.
Whether you will need to chunk the map and load it dynamically depends on a lot of things in your game and not just the size of the map. I would try to soldier on without it and see how the actual performance is without it. Because of course if you don’t need to do this, that is a lot of effort saved that could go towards furthering the development of the core of your game. You should also read this thread to make sure you are doing simple optimizations to ensure your map isn’t being rendered outside of the game view (if you follow some rules, Phaser will do this automatically and you often don’t need to chunk) and that you are using the most efficient tilemap options.
If you do follow the advice in that thread, load your map and it turns out it is a performance hog, I have seen a pretty nice tutorial on how to load chunks of it dynamically which can be found here.
I have not really tried to load the whole map.
The thing is that it will be at very least 2048x2048 tiles wide.
So if the data is stringified with json, that would be at least 12 Mo of data, just for the terrain…
(something like [[12,15,13,10,10,10,12,12, …]] with 2048x2048 values)…
Then there are much other things to load like trees, plants, players made objects.
So that’s definitely not a solution for me. It would be way too heavy on the players network.
Also about the links you’ve sent, they both use a layer as big as the whole map.
I’ve tried to make a 2048x2048 tiles wide empty dynamic layer, the game pumps 2Go RAM. Which is way too much for that solution to be usable for me.
Ideally I’d like to do something just as I drew, I’m kind of sure that it’s my best option.
Yesterday I’ve tried by creating a layer for each map chunk, but that ruins my FPS (even converting dynamic layers to static ones).
So I think I’ll try without using layers at all.
It sounds like you have checked out trying to load a map that big into memory and it causes problems. I definitely wasn’t saying it can handle it or you should.
It sounds like you should probably move on to chunking. I would probably say the tutorial I linked is the best I have ever seen at explaining a good way to do it with Phaser and I have kept my eye out for tutorials and articles on this topic for quite a while now. And as a bonus it is in Phaser 3!
I’ve think I’ve found a solution. I’m loading 150x150 tiles in 3 layers on screen (terrain / plants / trees), and when the character moves outside of the 50x50 tiles at the center, I load a 150x150 tiles around the character, destroy previous layers, rebuild them, rinse and repeat.
This is a video to show how it works : https://www.youtube.com/watch?v=IO60V805N9k
That’s far from perfect, there is a lot of optimization to do. But I think I’ll go this way.
Thank you for your help
Yes, it’s very experimental yet, still work in progress. The view will be closer to the character, and of course the players won’t see those grey areas at all.
I told you, when the player connects I load a 150x150 tiles area around his character.
This is 3x3 squares of 50x50 tiles, and the character is at the center.
When the character moves out of the center square, I load the 150x150 tiles area around him, I destroy all layers, and redraw them with new data.
That way, I always only have 150x150 tiles drawn at a time.
I use tiledb on the server side, to store the map data. And I have a websocket server, so that when the character gets out of the center square, the client sends a request to the server, the server checks the position of the character, loads the map data around him, and sends it back to the client, which then draws it.
There are lots of ways to make that better :
Instead of sending just 150x150 tiles data, send 450x450, so the client always have all the data that is around the character and drawing will be much faster, as it doesn’t require to send / receive a message to / from the server.
Also, don’t redraw the whole layer, copy / paste it on itself given the new position of the character, and then fill it with the map data.
I’m now working on other things, but that culling stuff is definitely a shitload of work.
Thanks! But actually, I was wondering more about the implementation, if you followed that tutorial, partially followed it or came up with your own implementation.
If you came up with your own, it would make a nice tutorial if you ever wanted to write it up. Resources on this for Phaser 3 are pretty scarce (the one I linked is the only one I am aware of).