Creating a tile-based map using a 2D array/dictionary without TileMap

Godot Version

4.6.2

Question

As practice, I’ve been challenging myself to try and create a very basic 2D tile-based map where the coordinates of a map are stored in either a 2D array or dictionary.

I want to do all this without using Godot’s built-in TileMap/TileMapLayer features.

As an example, I’m trying to create a grid that would correspond to 49 x 54 in size in pixels, and a cell_size of 422 x 212. My final goal is to use a chess-set image over it, with the visuals and data logic separated.

This is what I mean. This grid would actually be created purely in code, with the visual logic being entirely separate.

My issue is I’m having trouble wrapping my head around on how I would translate a 2D array/dictionary into an “invisible” grid? And I can’t find any resources tackling this topic that aren’t from 8 years ago.

Here’s the start of my code, through there isn’t much

class_name GridManager
extends Node2D


enum {
	EMPTY, PASSABLE
}

var tile_size: float = 49.0

#Tile size and cell size in pixels, stored in dictionary
var grid: Dictionary = {
 "tile_size": Vector2i(49, 54),
 "cell_size": Vector2i(422, 212),
}

func get_world_position(x: float, y: float) -> Vector2:
	return Vector2(x, y) * tile_size

func is_cell_vacant(pos: Vector2, target_pos: Vector2) -> bool:
	pass
	

I would advice against using a dictionary just for storing two often used variables. Just use variables:

var tile_size := Vector2i(49, 54)
var cell_size := Vector2i(422, 212)

The easiest way to use dictionary for the grid is just to use the cell position as a key. Here, I’m assuming that an int is good enough to tell what the cell contains. But that could be String or float or Dictionary or whatever.

var grid: Dictionary[Vecto2i, int]
for y in 212:
    for x in 422:
        grid[Vector2i(x, y)] = <cell content, whatever it is>


If you are willing to convert your tiles to TextureRects, a GridContainer might be a good solution for you.

Thanks for this, its helping me on the right track.

What I want to do is, through the player script, determine if each tile is walkable or not. I suppose in my case right now, all the tiles in this grid would be walkable.

So essentially I want to convert the coordinates stored in the dictionary or 2D array (depending on what I go with, leaning towards dictionary) into data to create the walk area for the player.

I was thinking of using a boolean that determines if the player can move or not. Would this be sound?

Is the movement going to be like on a chess board, player moves from cell to cell? If yes, then bool per cell will be fine.

Continuing on with Dizzy_Caterpillars logic…
A cell is going to be an important object in this game no matter which way you take it.
This is a perfect candidate for a class.

class_name Cell
var walkable:bool = true   
var what_is_on_me:ChessPiece = null 
var address:Vector2 
var index:int    
# you will know what kinds of things to build out the class

and then it is
grid[Vector2i(x, y)] = Cell.new()

This is really putting me on the right track, thank you! Do you mind explaining a little on how I could use the address and index variables?

The address is the row,col coordinate in the tile grid; top left cell being at 0,0, then 0,1 and on.
The index is an integer corresponding to the linear set of cells; top left cell being 0, then 1 and on.
Neither are absolutely necessary. I just remember that every time I do a grid I end up using at least one of those systems to locate cells.