0 votes

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.

Godot version 3.3 Stable Official Win64
in Engine by (47 points)

1 Answer

0 votes

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.

by (3,389 points)

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?

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:

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?

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.