How to go about generating a very large or infinite map from tiles?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By batmanasb
:warning: Old Version Published before Godot 3 was released.

I’m hoping to make an open world top-down game, so naturally I need a bunch of tiles. But I think the tiles will just be ground textures, such as grass, sand, and water. Foliage and other objects can just be sprites in some kind of physics body. I was going to generate the level as you move around and maybe if performance is an issue, I’ll figure out a way to remember the layout and delete it then respawn it as the character returns to the area. But the real question is whether anyone here knows a good way to implement an infinite or very large map of tiles. I’ve never used the Tilemap node but it looks like you can’t modify it at runtime, so maybe I could just generate a large Tilemap if that’s an efficient solution for handling a large amount of tiles. I’ve still got some work that needs to be finished before I start working on generating the world, but I thought it couldn’t hurt to look for ideas early.

:bust_in_silhouette: Reply From: Bojidar Marinov

You can change a tilemap’s tiles viaset_cell and set_cellv. E.g:

get_node("TileMap").set_cell(x, y, TILE_GRASS)
get_node("TileMap").set_cellv(Vector2(x, y), TILE_GRASS)

…Where, TILE_GRASS is a constant signifying the ID of the grass tile.

From: TileMap — Godot Engine (latest) documentation in English

This seems like it may be very slow for larger maps since the OP would essentially need to create a huge .json map (to save the world) and then call TileMap.set_cell() for each position in a script-driven loop. Maybe a feature request is in order here for methods on the TileMap capable of saving a copy of itself into user:// (and the corresponding function to load the saved tilemap). TileMap.set_cell() might be useful for RPGs changing the odd tile here and there as the story progresses and responds to player actions but is likely highly inefficient for large sandbox type maps like the OP asked about.

gau_veldt | 2016-03-09 17:46

Idk, the TileMap looks like like it can hold an infinite number of tiles, and it seems to divide them up into quadrants automatically, so it’s optimized. This looks like it could work. The only issue now is generating the map. Doing it in a large loop is a bad idea and can lead to crashes, since it takes too long. So I think if I figure out some sort of algorithm that generates then on the move, say maybe ~15 tiles at a time, then this could work.

batmanasb | 2016-03-09 23:55

@batmanasb You could generate JSON files per quadrant/chunk limiting the loop to 256 passes per 16x16 chunk (quadrant size set to 16).

gau_veldt | 2016-03-10 00:25

@gau_veldt Could you explain the process? I don’t quite understand.

batmanasb | 2016-03-10 04:13

var qsize=mymap.get_quadrant_size() will obtain the map’s quadrant size in a script allowing it to be calculated which quadrant a particular cell position is within. When generating the cells in a quadrant not saved the quadrant’s cells can be scanned in x and y for new cells on (qsize*xquad)+x,(qsize*yquad)+y over x in range(256), y in range(256) where xquad is the current x quadrant int(x_pos/qsize) and yquad is the current y quadrant int(y_pos/qsize). x_pos and y_pos is some cellwise location within the tilemap. The cells within the quadrant are stuck into a dictionary (to allow empty cells) and saved somewhere in user:// in json format using a File (get_line, store_line) and the savegame json (to_json to store_line, parse_json from get_line).

for loading it comes down to checking if the visible portion of the map has quadrants not loaded from the saved map and loading the json files and iterating the loaded data to call set_cell as needed. one would then set some boolean mapping of map chunk x and y coordinates to indicate this chunk is now loaded. you would clear this upon entering a new map (starting the game) or if a chunk’s content has been rewritten. Loading the saved map data only as needed prevents loading an entire map’s content, localizing loading to the areas the player is visiting.

gau_veldt | 2016-03-10 17:52