So I suppose this is the way to go for now? Are there plans to add support for nested typed arrays in the future?
var _adjacency_matrix: Array[Array]
func setup(p_size: int) -> void:
size = p_size
for i in range(size):
_adjacency_matrix.append([])
for j in range(size):
_adjacency_matrix[i].append(j)
func populate() -> void:
var n = 0
for i in range(size):
for j in range(size):
n += 1
var vertex := Vertex.new()
vertex.label = str(n)
_adjacency_matrix[i][j] = vertex
Currently my solution is to use a dictionary with a Vector2I as the key, the downside is that you lose some performance in lookups but depending on how fast you need it, might be a valid solution.
var grid = Dictionary[Vector2I, int]
That said you could just use linear arrays like mentioned. And remember if you know the size, you can calculate always calculate the linear index from the X,Y coordinate for example
# Note my for loops assume you want to go
# "right-to-left" and "top-to-bottom"
# 0,0 being top left
var size : Vector2i = Vector2i(10, 15)
var _adjacency_matrix: Array[Array]
func setup(p_size: Vector2i) -> void:
size = p_size
_adjacency_matrix = Array[size.x * size.y]
func populate():
for y in range(size.y):
for x in range(size.x):
var index = x + (y * size.x)
var vertex := Vertex.new()
vertex.label = str(index)
_adjacency_matrix[index] = vertex
gdscript does not support multi-dimensional arrays and it might never do.
you have to pretend this is C and hard code it yourself.
luckily I already did, here’s my Voxel resource that I used to handle 2D matrices, you can adapt it to your needs (use of int):
class_name Voxel
extends Resource
var map : Array[int] = []#TODO multiple voxels for layers same resource
var voxel_height : Array[int] = []
var map_size : int = 64#size of matrix
var hmapsiz : int = 32#half size of matrix
func _init(mapsize : int) -> void:#new() with argument size of same side square. this can be done differently for uneven squares.
map_size = mapsize
@warning_ignore("integer_division")
hmapsiz = map_size / 2
populate_voxel()#generate matrix fill with 0
#func _restart(MapSize : int) -> void:
#map_size = MapSize
#map.clear()
#_initialize(mapsize)
func populate_voxel() -> void:#I'm using 2 identical matrices
for i in range(map_size):
for j in range(map_size):
map.append(0)
voxel_height.append(0)#you can remove code for one of these
func set_voxel(pos : Vector2i, value : int, type : int = 0) -> void:#set item at pos in array ID type
match type:
1:
if len(voxel_height) > pos.x * pos.y:#prevent overflow
voxel_height[(pos.y * map_size) + (pos.x)] = value
_:
if len(map) > pos.x * pos.y:
map[(pos.y * map_size) + (pos.x)] = value
#NOTE godot arrays can accept negative values for some stupid reason
func get_voxel(pos : Vector2i, type : int = 0) -> int:
match type:
1:
if len(voxel_height) > pos.x * pos.y:
return voxel_height[(pos.y * map_size) + (pos.x)]
else:
return voxel_height[0]
_:
if len(map) > pos.x * pos.y:
return map[(pos.y * map_size) + (pos.x)]
else:
return map[0]
func check_inside(cpos : Vector2i) -> bool:#this ensures a tile has tiles around it
return cpos.x > 1 and cpos.x < map_size-1 and cpos.y > 1 and cpos.y < map_size-1
Multidimensional arrays are relatively easy to embed in regular arrays, particularly if your array dimensions are power of two in size.
Say we want an array with dimensions (3, 7):
var x_size = 3
var y_size = 7
var cells = x_size * y_size
var array = []
func init_array():
for i in cells:
array.append(0)
func dump():
for y in y_size:
for x in x_size:
print("%d, %d -> %d" % [x, y, array[(y * x_size) + x]])
func get(x: int, y: int) -> int:
var idx = (y * x_size) + x
return array[idx]
func set(x: int, y: int, val: int):
var idx = (y * x_size) + x
array[idx] = val
If your array sizes are powers of two, you can do this with shifts rather than multiplication, which is much faster:
Note that with this scheme, if you want to loop over coordinates, it’s better to have y in the outer loop; that will result in linear access to memory:
var x_size = 4
var y_size = 4
for y in y_size:
for x in x_size:
print((y * x_size) + x)
---
0
1
2
3
4
5...
---
for x in x_size:
for y in y_size:
print((y * x_size) + x)
---
0
4
8
12
1
5...
Modern systems run much faster with linear sequential memory access.