Sign in to follow this  
cebugdev

2D huge tile maps handling?

Recommended Posts

Hi all,

 

how to handle huge tiled maps? i know that we only render the tiles which is visible in camera but how will the nonvisible tiles be handled?

 

1. is the map loaded into a separate surface at the back and then just BlitBlk or screen surface transfer from the entire map surface to screen surface for rendering? i think this is costly like for example we have a pretty huge map, does that mean i need to create a huge back surface too?

also, some surfaces like that of HTML5 canvas has maximum size limit.

1.a Do i need to create multiple surfaces instead to handle the entire map?

 

logical array->surface temp ->main screen surface

 

2. Will the rendering only from the logical map array (example 1= grass, 2=rock)  to the screen surface directly based on player current location and not render the entire map in a back surface?

 

logical array->main screen surface

 

 

how do professional tile based RPG games handle this?

 

Thanks

Edited by cebugdev

Share this post


Link to post
Share on other sites

Let's explain it like this.

You have two cameras.

One camera renders everything that should be seen. It does not care about what lies beyond it's gaze. Only that once it enters view, it's immediately rendered.

Then you have a second camera which buffers data outside of the camera's view. Unlike the rendering camera, it does not actually render anything into a visible image. It just loads data in case that it will be rendered. For levels, typically you have everything loaded at once. For huge worlds, you collect only what you need in a radius.

Share this post


Link to post
Share on other sites

When dealing with large maps you only need to render what will be seen by the player and skip the rest of the map to save memory.  For example if I have a world that is 2000x1000 tiles it would be crazy to try and render this whole map in a timely fashion.  That would be 2,000,000 total tile I would have to render and this is only for one layer!  Ouch that could be VERY costly on even the fastest computers.

 

This explanation is complicated and has a lot of calculations so please bear with me.  We are going to need to track a lot of different variables to help reduce our iterations to something that is manageable.  Notice in my world definition I talked about the size of the world in tiles and not pixels.  This is because with the beauty of tiles we can male them just about any size we want which also changes the size of our world.  It is also possible to mix tile sizes for different layers but that is another topic.

 

Now then the first thing to wrap your head around is that your players avatar should typically not move around your computers monitor, meaning it will mostly be drawn in a single location on the monitor.  But instead the world coordinates will move which means the tile map is what you want to move around to simulate the movement of the player.  I lost a couple of programmer in collage when I tried to explain this but the concept is still true.  This is also known as the players screen coordinates.

 

Knowing where the player is located in world coordinates will help us do the first calculation which is figuring out the upper left corner of the world that needs to be drawn.  To do this we would just need to know the screen resolutions and subtract half the height and width from the players world coordinates.  For example if the game resolution is 1024x768 we would want to take the players world x coordinate and subtract 512 (1024 / 2), and then subtract 384 from the players world y position.  This would then give us the top left world position of the tile map.  

 

The next step is to take the world position which would be in pixels and convert it to tiles.  To do this we would now need to know the width and height of your tiles.  for an example we will just use a 32x32 tile just so the math will be easier.  We would take the upper left world position x and divide it by 32 and do the same to the y coordinate.  This would then give us the starting tile number to start drawing at and we would then just add enough tiles to cover the screen.  Again if we are using the 1024 x 768 resolution we would just divide 1024 by 32 which equals 32, and also 768 divide by 32 equals 24.  Got to love some nice and simple math... Now that we have a starting tile and the ending tile we will iterate through our tile array and only draw these relevant tiles.  Oh and this little optimization take the 2,000,000 original tiles to draw in one frame down to 768 tiles.

 

Now once you start moving the world map around you may want to expand the number of cols and rows enough so that you don't get clipped tiles showing on the game world.  But this will be something you'll want to experiment with until you find a happy medium.

 

If your also having to deal with an even bigger world map you could apply this same concept to the tiles data structure and as the player moves around the world and gets close to the worlds border it would then pull the data from your hard storage.  Just make sure that when the player is moving around their computer isn't going to the hard storage every couple of frames.  What I mean by hard storage is if your hosting an internet game it would be loading from the internet, or if they are playing locally on the computer pulling it off the hard drive.  Again this will be something you will need to play around with to try and find the right sweet spot for when to poll for new data.

Share this post


Link to post
Share on other sites

Tangletail explains the concept well. To implement this, you'll want a map data structure and file format that lets you handle 'chunks' of the map as a unit, rather than trying to pull only what you want from a monoliithic map structure (e.g. a big array of tiles in memory or on disk).

 

So, rather than a giant array of tiles, you want to break your map into regular pieces -- you can choose different sizes to suit your needs, but for now lets just say that chunks are 16x16 tiles (power-of-two squares have some nice properties that can be used to optimize some of the math you'll need to do). The chunks themselves are just smaller versions of the big array.

 

On disk, your map file won't be a big array of tiles any more, it will be a smaller array of chunk references, and a list of chunks. From disk, you load whole chunks whenever any part of it is within the radius you care about.

 

In memory, your map structure is similar to the disk contents -- One option is to load the entire array of chunk references into memory, which you use to determine which chunks are nearby and need to be loaded. If your maps are really big, you might increase the chunk size or even chunk up the array of chunk references (giving you two layers of indirection, instead of just one). When a chunk is inside your area of interest, it needs to be in memory -- and when a chunk you've previously loaded goes outside the area of interest, you can re-claim that memory so it can be used for another chunk. This works really well with memory management pools -- You set aside enough memory for the maximum number of chunks that fit inside your area of interest, and maybe a bit more, and then you just re-use those chunk structures over and over to hold different chunks as the player moves around. The chunks in memory don't have to be stored in map-order, the array of chunk references takes care of spacial ordering.

 

This is all pretty straight-forward, but you're dealing with a few different coordinate systems here (the camera view, the area of interest, the coordinate system of the array of chunk references (and one of those for each layer of chunking), and the coordinate system of the chunks themselves) so there are a lot of little details to get right.

 

 

Now, all that assumes that the world is sort of static -- if not, you'll need to additionally track which chunks the player has changed, and write those changes back to disk somehow, and you might need to do that per-player if they have independent worlds. 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this