How could I create a data system for Tiles?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Phuple

Alright, so im fairly new to godot, and im working on a small project that requires me to store some sort of data in Tiles, for instance, if the user has interacted with a tile or not (Silly example). Only problem is I have no clue how I would go about doing this.

Ive tried looking online but I found alot of comments under posts/questions saying that there is no way of doing what I need, could anyone confirm, and if true is there another method I could use?

:bust_in_silhouette: Reply From: Inces

From what I heard Godot 4.0 does have built-in data system for tiles. In Godot 3.4 You need to make custom one. It is very basic, just create a dictionary with tiles as keys, and your data as values. It woill look for example like this :

var tiledata = { (0,0) : {"interacted" : true, "durability" : 3},(1,0) : {"interacted":false,"durability":5}, (1,2) : {andsoon

You will have to manually update this dictionary in any way You need.

Yeah just switched over, feels great and thanks for the help! :slight_smile:

Phuple | 2022-02-22 15:54

Alright I also just ran into another issue, how could I access said custom_data_layer? I am having so much trouble, I tried:
self.tile_set.custom_data_layer
But that returns the error Invalid get index custom_data_layer (on base: TileSet)

Phuple | 2022-02-23 00:49

Sorry for the flood of comments but im making a bit of progress, I found the get_custom_data property under the TileData object but when I try

var tile_data = TileData.new()
tile_data.set_custom_data("test", "test")
print(tile_data.get_custom_data("test"))

it returns:
Condition !tile_set is true for the 2nd line and:
Condition !tile_set is true. Returning Variant() for the 3rd

Phuple | 2022-02-23 00:49

:bust_in_silhouette: Reply From: rakkarage

another way is to use an 1d array and encode the xy into an index
it takes more setup and work but I think it may be worth it in some cases?
all the keys are redundant if calculable from index?
and arrays and array lookup usually faster

pixelarray2d.jpg

extends Control

var _testDictionary := {
	Vector2i(0, 0) : {"interacted" : true, "durability": 3},
	Vector2i(1, 0) : {"interacted" : false, "durability": 5}
}

var _testArray := [
	{"interacted" : true, "durability": 3},
	{"interacted" : false, "durability": 5}
]

static func _index(x: int, y: int, width: int) -> int:
	return int(y * width + x)

static func _position(i: int, width: int) -> Vector2i:
	var y := int(i / float(width))
	var x := int(i - width * y)
	return Vector2i(x, y)

func _ready():
	print(_testDictionary)
	print(_testDictionary[Vector2i(1, 0)].durability)
	print(_testArray)
	var index = _index(1, 0, 2)
	print(index)
	print(_position(index, 2))
	print(_testArray[index].durability)

Output

{(0, 0):{interacted:true, durability:3}, (1, 0):{interacted:false, durability:5}}
5
[{interacted:true, durability:3}, {interacted:false, durability:5}]
1
(1, 0)
5

have not tried it in 4 yet but this should work there too

:bust_in_silhouette: Reply From: Phuple

The issue was solved, for any future viewers (Godot 4.0)

var source_id = self.get_cell_source_id(0, Vector2i(0,0), false)
var get_tile_pos = self.get_cell_atlas_coords(0, Vector2i(0,0), false)

var source = self.tile_set.get_source(source_id)
	
var DATA = source.get_tile_data(get_tile_pos, 0).get_custom_data(name)

You need to replace Vector2i(0,0) with the position of the tile, the way I did it was:
world_to_map(get_global_mouse_position()) and just saved that to a variable:)