How can I go through instances of a node?

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

Hello!

There are cards in my small memory game and I would like go through instances of a card node.
But when I try this with a for loop:

var cards=get_node("cardnode")
for acard in cards:

I get this error message: “Unable to iterate on object of type ‘Object’.
What is wrong this? I have no more idea to check whether two sprites are matching in two instances of a node.

:bust_in_silhouette: Reply From: timothybrentwood

If your node structure is:

cardnode
>card1
>card2
>card3

You want to use:

var cards = get_node("cardnode").get_children()

If you are instancing your cardnodes in code then wanting to iterate through that list later add:

var new_card = card_scene.instance()
# do the rest of the setup work including something.add_child(new_card)
new_card.add_to_group("cards")

at the time of instancing. Then your loop is:

var cards = get_tree().get_nodes_in_group("cards")
for acard in cards:

Let me know if you’re doing something else.

Hello!

I instancing the cardnodes in an other node when the scene starts:

func _ready():
	randomize()
	var card=preload("res://cards.tscn")
	while canexit==false:
		var c=card.instance()
		var k: Sprite=c.get_node("cardsprite")
		get_parent().add_child(c)
		cards.append(c)
		c.position.x=herex
		c.position.y=herey
		var rn=randi()%13+1
		while rn in imagearray:
			rn=randi()%13+1
		imagearray.append(rn)
		c.itssprite=rn
		numofcards+=1
		if numofcards>=13:
			herex=4
			herey+=k.texture.get_size().y+4
			canexit=true
		else:
			herex+=k.texture.get_size().x+4
			if herex>=(get_viewport_rect().size).x-k.texture.get_size().x-4:
				herex=4
				herey+=k.texture.get_size().y+4
				if herey>=(get_viewport_rect().size).y/2-k.texture.get_size().y-4:
					canexit=true

So, the cardnode has no child nodes, only a sprite. The type of the cardnode is a Node2D with a sprite child node. Only these two nodes exists in cards.tscn.
As you can see, I already put the card instances into an array (cards.append(c)). If there is no other option, it would be good go through on this cards array, but I don’t know how can I access to an array from a node of an other scene?

Tomi | 2021-05-21 12:02

var cards = get_node("cardnode").cards

The better way to handle it is to let the engine manage the card nodes. If you queue_free() them you’ll be left with a null in your array but the engine will clean up that null automatically:

var c=card.instance()
var k: Sprite=c.get_node("cardsprite")
get_parent().add_child(c)
c.add_to_group("cards")
c.position.x=herex
c.position.y=herey

Then your loop is:

var cards = get_tree().get_nodes_in_group("cards")
for acard in cards:

timothybrentwood | 2021-05-21 14:24

I put over my code into that node which creates the cards. So, I re-edited the structure of my program a bit.
Now this is the piece of code in the main Node of the Scene:

func _process(delta):
	if (Input.is_mouse_button_pressed(BUTTON_LEFT)):
		var mousex=get_global_mouse_position().x
		var mousey=get_global_mouse_position().y
		for j in range(0,cards.size()):
			if mousex>cards[j].position.x and mousex<cards[j].position.x+cardwidth and mousey>cards[j].position.y and mousey<cards[j].position.y+cardheight:	
				var k: Sprite=cards[j].get_node("cardsprite")
				if card1==null:
					card1=cards[j]
					k.texture=sprchanger(cards[j].itssprite)
				elif card2==null and card1!=cards[j]:
					card2=cards[j]
					k.texture=sprchanger(cards[j].itssprite)
					if card1.itssprite==card2.itssprite:
						for m in range(0,cards.size()):
							if cards[m]==card1:
								card1.queue_free()
								card1=null
							else:
								card2.queue_free()
								card2=null
							cards.remove(m)
							break
					else:
						card1.get_node("cardsprite").texture=load("res://cardbackground.png")
						card2.get_node("cardsprite").texture=load("res://cardbackground.png")
						card1=null
						card2=null

But after I delete the two cards with similar texture with queue_free() and remove commands, I get this error message:
Invalid get index ‘25’ (on base: ‘Array’).
maybe because the j loop doesn’t know which element is deleted and that cards.size() is changed.
So the question is only that how can I delete an element from an array without confusing it?
Maybe I overcomplicated the method of deleting in my code?

Tomi | 2021-05-21 15:12