How to access other class variable and how does find function ?

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

I am making a board game in which I have hextiles. I am instancing hextiles in a hex formation. After that, I would like to updates the neighbour of each tile, so that I can start to implement graph functions.

Here is how I check the and want to add the neighbours to each tile :

var look_up_table_neighbour = [Vector2(1,0), Vector2(1,-1), Vector2(0,-1), Vector2(-1,0), Vector2(-1,1), Vector2(0,1)]

func hex_neighbour(var hex, var direction):
	var dir = look_up_table_neighbour[direction]
	return Vector2(hex.tile_position.x + dir.x, hex.tile_position.y + dir.y)

func update_neighbours():
	for hex in get_children():
		for i in range(0,6):
			var corresponding_neighbour = get_child(get_children().find(hex_neighbour(hex,i)))
			hex.add_neighbour(corresponding_neighbour)

And here is my tile script :

export var tile_position = Vector2()

var neighbours = []

func add_neighbour(var hex):
	if not neighbours.has(hex):
		neighbours.append(hex)
		hex.neighbours.append(self)
		var label = get_node("Label")
		label.set_text(str(neighbours.size()))

My first problem is the Array.find function. What does it exactly do? Does it compare each parameter of the object inside of it? Or does compare the ID of object?

My second problem would be in accessing the variable “neighbours” in other hex. However I think what I put here works (just the find function that blocks me).

Regarding your first question
[!] No guarantee here because I am not a dev…
I believe the objects inside an array are compared by reference (pointer) and the find-function returns the position of the first object which has the same reference in memory. This can be important when some of your objects have the same value and therefore they are referencing to the same memory block.

I tried to investigate this further with this script (save it as array_test.gd and run it inside a terminal with godot -s array_test.gd):

#array_test.gd
extends SceneTree

func _init():
    # Declare a, b, c
    var a = Vector2(0,0)
    var b = Vector2(1,0)
    var c = Vector2(0,0) # <- Same value as 'a' but different variable
    
    # Append all to the array
    var arr = Array()
    arr.append(a)
    arr.append(b)
    arr.append(c)
    
    # Find their positions
    print("a: ", arr.find(a))  # <- 0
    print("b: ", arr.find(b))  # <- 1
    print("c: ", arr.find(c))  # <- 2
    
    quit()

The print statements are as follows:

a: 0
b: 1
c: 0

This could substantiate my thesis but I am no c++ expert so please don’t blame me if my conclusion is wrong. :stuck_out_tongue:
I am not sure if this behaviour is the same with more complex objects. Will investigate further when I find the time.

rolfpancake | 2017-12-12 19:07

:bust_in_silhouette: Reply From: Zylann

get_children() returns an array of all child nodes. find iterates all elements in an array and returns the index of the first element which is equal to the one you want to find.
Two node elements are equal if they point to the same node (it’s reference comparison).

In your code, you are giving find a Vector2. However, the array returned by get_children is an array of nodes, not an array of Vector2. So find will not find anything, and will return -1.

If you want to find hexes from coordinates, I suggest you build an two-dimension array yourself in which you store a reference to your hexes, and then finding neighbors will be as easy as this:

var top_right_neighbor = grid[x+1][y-1]

# This would be a square grid, but considering they are hexes, you would need
# to take some skew into account, because hexes have 6 neighbors, not 9.
# but I'm sure it can be represented with a 2D grid

Or you can make it as a dictionary with Vector2 keys, works too.

Alternatively you could add variables on your tiles that contain their neighbor (building a graph), but that could be very tedious depending on the size of your map.

Thanks for the answer :slight_smile:

I figuered the comparison by my own. I was aware that get children() return an array, that’s what I wanted wanted to use find (I also knew find would return me the index inside the array).

In the end, I decided to make my own “find” method. I didn’t wanted to put a copy of my hexes inside an array, because I generate a lot of them and I can iterate through my scene tree. I didn’t wanted any duplicates.

mmarramarco | 2017-12-12 22:40

Ok^^ my idea of using a grid was not purposed to have duplicates though, but to have an alternative data structure. The scene tree alone isn’t optimal to work on a grid-like world like tiles or hexes, so trying to find nodes by iterating all of them will be quite slow. I guess it’s fine if the lag is not noticeable :wink:

Zylann | 2017-12-12 22:55