Tilemap Scrolling With a Chunked World

Hello -

I’ve been implementing a chunking system for my 2D game, so that I can load only part of my huge world at once. The problem I’m having is transitioning my current rendering code to one that can actually work with a world bigger than the screen. My current code draws everything relative to the screen (the Tilemap is the size of the screen), and I need to draw things relative to the world so that I can scroll around it, as it is much bigger than the screen.

To start, I’m having trouble figuring out how to size the Tilemap. What I’d like is to load every chunk surrounding the chunk that the player is in, meaning there are 9 chunks loaded at all times, and 3 get unloaded/loaded whenever needed. To have them loaded at all times, would I size the Tilemap to the size of 3 chunks x 3 chunks?

And for scrolling, would I just move the Tilemap around? But if I do that, won’t the edge of the Tilemap eventually be reached? Is it the camera (screen) that should be moving, or the world (Tilemap)? Should the Tilemap be the size of the whole world? But then wouldn’t that defeat the purpose of chunking (loading only what’s needed)?

Sorry for having so many questions, I just can’t seem to find definite answers anywhere.

To try and summarize, here are the 3 main questions I have:

How do I size the Tilemap to allow for clean loading/unloading of chunks?
How do I update the Tilemap when loading/unloading occurs?
What is it that I move to scroll, the camera or the world?

Thanks for any insight.

How do I size the Tilemap to allow for clean loading/unloading of chunks?

Your tilemap should be the size of the visible screen (stage.stageWidht, stage.stageHeight) and you should have a tilecontainer that contains everything else. Messing with the size and position of Tilemap is a headache.

How do I update the Tilemap when loading/unloading occurs?

I would keep every “chunk” into his own tileContainer and then add them or remove them from a BIG tileContainer that scrolls arround.

What is it that I move to scroll, the camera or the world?

Some people can think in “cameras”. I can’t. I move the entire world so that I am looking at the action.
In this case, not moving the tilemap but moving a tilecontainer that contains everything else.

Your structure should be something like this:

  • Tilemap
    • world TileContainer
      • Chunk
      • Chunk
      • Chunk

Or at least thats how I would implement it :stuck_out_tongue:

So would the large Tilecontainer be empty in the places that aren’t loaded (meaning there is either a chunk, which is loaded, or there is nothing at a given position), or would they all be filled with the world data, just drawn as needed (every position has a chunk, it just may or may not be loaded)?

Thanks for the help, I’m starting to understand it better now.

by removing the “chunk” tilecontainers from the “world” tilecontainer you will leave empty places that aren’t loaded and won’t slow you down with the rendering :wink:

And I just have one more question -

I got the architecture working, with a world TileContainer filled with chunk TileContainers, as well as a Tilemap the size of the screen.

However, Tile (and therefore TileContainer) aren’t DisplayObjects, meaning they can’t be rendered (added as a child of the main screen). To render them, I have to place them in the Tilemap, which is a DisplayObject. Wouldn’t that mean that I couldn’t load anything off-screen? And if not, how would you suggest doing so?

They aren’t displayobjects but they can be added to the screen when they are added to a tilemap that is added to the screen.

Why do you think that you need to add them to the screen to “load” them? or what do you mean by “load”? :thinking:

this (for example) creates and sets the values of a tile and never puts it on screen. However that tile is an object that exists and retains his identity. Whenever it is added to the screen it will show the information he has accordingly.

var tile = new Tile();
tile.id = 4;
tile.tileset = myTileset;
tile.x = 100;
tile.y = 200;

to add it to the screen you do

By “loading” chunks, I meant that the only part of the world that is loaded is those chunks. The implementation I was thinking of was finding whatever chunk the player is in, loading it, and then loading all chunks surrounding it. As the player approaches the edge of the chunk they are in, the 3 chunks they are moving away from are “unloaded,” and the 3 chunks they are moving towards are “loaded.” Essentially, I was hoping to draw (load) tiles outside of the camera view (Tilemap), and then adjust what is being loaded as needed (as the player moves)

Here’s a diagram of what my thought process was:

The red square is the chunk with the player, and the 8 black squares surrounding it are the chunks that are loaded. The rectangle that intersects them is the Tilemap. Would this work with what you are saying? Or would a different method be more effective for the loading/unloading and scrolling I’d like?

The ram footprint of a tilecontainer full of tiles shouldn’t be too big.

I would keep all my chunks created in a array, bidimentional array, map, etc. and then addTile and removeTile as the user approaches an edge of the current chunk.

I finally got some time to implement it, and it worked. I just had one problem:

The issue is that I want to be able to scroll smoothly. To do this, I need to be able to render partial tiles when the player has moved by a factor less than the size of a tile, to provide the smooth transition (compared to the choppiness of moving everything abruptly an entire tile).

From my understanding:

  • Tiles are drawn from their top left corner, and it is impossible to render a tile with a top left corner off-screen (or rather, off-Tilemap)
  • When you change the width/height of the Tilemap, it just extends it down and to the right.
  • There is no way to shift the top-left of the Tilemap, let alone outside of the screen.

And if all of those things are true, I have no idea where to begin with implementing it with some way that isn’t completely inefficient.

What would be ideal for me would be to have a Tilemap that is 2 tiles wider and 2 tiles taller than the screen, centered (meaning there’s a 1-tile border around the screen), and that would be what was drawn, to allow for partial tiles. I can’t implement this, though, if it’s true that you cannot move the top left of the Tilemap.

Is there a way I could get that to work, and if not, do you have any suggestions for getting smooth scrolling some other way?

Thanks for any help.

Regarding tiles to be rendered off-tilemaps, I faced the same issue and had to modify the Tilemap classes to disable clipping (which is ON by default).
I’m not using the latest version of OpenFL though, so it’d take some time to make a PR on the current version if you need this feature :slight_smile:

What if you put all the tiles in a TileContainer and move the TileContainer as needed?

Then the Tilemap could stay the same width/height in the same place

I tried that, but I’m still having the same problem. I want to be able to scroll by units less than the dimensions of a tile, and I can’t draw tiles within the TileContainer whose top left corner (where they are drawn from) are outside the Tilemap. I have it to work with moving tile by tile, but the effect I’m looking for is more smooth and precise than that.

The current implementation I have is a Tolemap that stays still while the Tilecontainer moves around, I just can’t figure out how to draw tiles that have some section off-screen and some on-screen.

If you put a 16x16 tile at -8,-8 directly to your tilemap you would see a 8x8 fraction of the tile.

The tile doesn’t have to be fully in to be rendered.
There is no need to make the tilemap bigger than the screen. Make it exactly the screen size and forget it even exists.

I’ll try that, thank you.