Help on how to Assign a Shape to a CollisionShape2D Node in GDScript

Godot Version

godot v4.2.1

Question

I’m trying to create a card game, but I’m stuck on how to assign a shape to the CollisionShape2D node within the giveSpriteTexture() function using GDScript. I’ve attempted a few methods, but I keep encountering a “null instance” error. I’m not sure if I’m using the .shape property incorrectly or if I’m trying to assign a shape to a non-existent node. I’m considering whether I should create a separate scene for the card nodes to avoid specifying the shape and size in GDScript. However, I’m curious about how to properly do it with GDScript. Can you help?

CODE

extends Node2D
# array to store all cards in the deck
var deck : Array
var deckAreaNodes : Array
var deckCollisionNodes : Array
#card sprite size 42x60 pixels

# Called when the node enters the scene tree for the first time.
func _ready():
	makeDeck()
	makeNodesForCards()
	giveSpriteTexture()
	var xpos = 20
	for i in deck.size():
		get_node(deck[i]).position.x = xpos
		get_node(deck[i]).position.y = 30
		xpos += 20
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	pass

#add cards to deck array repeating 4 * 13 times for every card color and number
func makeDeck():
	for i in 4:
		for j in 13:
			if i == 0:
				deck.append("card_diamonds_"+str(j+1))
			if i == 1:
				deck.append("card_hearts_"+str(j+1))
			if i == 2:
				deck.append("card_spades_"+str(j+1))
			if i == 3:
				deck.append("card_clubs_"+str(j+1))

# make nodes for cards sprite node > area2d > collision2d
func makeNodesForCards():
	var AreaNodeName = "a"
	var collisionNodeName = "c"
	# repeat for every array enrty
	for i in deck.size():
		var cardSprite = Sprite2D.new()
		var cardArea2d = Area2D.new()
		var cardColission2d = CollisionShape2D.new()
		#adds sprite as child to board node
		add_child(cardSprite)
		#adds area 2d and collison node as child to sprite
		cardSprite.add_child(cardArea2d)
		cardArea2d.add_child(cardColission2d)
		#change name of nodes to the same ass deck array
		cardSprite.name = deck[i]
		#changes name to area node + deck array name 
		cardArea2d.name = AreaNodeName+deck[i]
		# same as above but for collision
		cardColission2d.name = collisionNodeName+AreaNodeName+deck[i]
		#add nodes names to array
		deckAreaNodes.append(str(cardArea2d))
		deckCollisionNodes.append(str(cardColission2d))

#adds correct texture to card 
func giveSpriteTexture():
	for i in deck.size():
		var tempNode = "/root/"+deck[i]+"/"+deckAreaNodes[i]+"/"+deckCollisionNodes[i]
		get_node(deck[i]).texture = load("res://ASSETS/"+deck[i]+".png")
		get_node(tempNode).shape = RectangleShape2D
		

I think you have to set the shape to an instance of an object of type RectangleShape2D:

.shape = RectangleShape2D.new()
.shape.size = Vector2(100, 100)

Do you mean like this in the giveSpriteTexture(): funtion?

func giveSpriteTexture():
	for i in deck.size():
		var tempNode = "/root/"+deck[i]+"/"+deckAreaNodes[i]+"/"+deckCollisionNodes[i]
		get_node(deck[i]).texture = load("res://ASSETS/"+deck[i]+".png")
                #like this?
		get_node(tempNode).shape = RectangleShape2D.new()
		get_node(tempNode).shape.size = Vector2(100, 100)
		

If so, I get the “error ‘Invalid set index “shape” (on base: “null instance”)’ with a value type of ‘RectangleShape2D.’”

I think this means that I’m applying .shape to a node that does not exist or does not have the .shape property, but I’m not sure.

I also tried to do

func giveSpriteTexture():
	for i in deck.size():
		var tempNode = "/root/"+deck[i]+"/"+deckAreaNodes[i]+"/"+deckCollisionNodes[i]
		get_node(deck[i]).texture = load("res://ASSETS/"+deck[i]+".png")
		$cacard_diamonds_1.shape = RectangleShape2D.new()
		$cacard_diamonds_1.shape.size = Vector2(100, 100)

where $cacard_diamonds_1 is the node name for the CollisionShape2D in the first card.

Was there an error when trying the second method with a direct reference to your CollisionShape2D node?
Have you tried to check if there is a node with your tmpNode node path?

print(get_node(tmpNode) != null)

I get the same error with $ and get_node(), print(get_node(tmpNode) != null) prints false. I also tried:

print(get_node(“/root/card_diamonds_1/acard_diamonds_1/cacard_diamonds_1”))

but it returns object#null, so I’m assuming I have the wrong path to the node. However, when I look in the Remote tab while running the game, the nodes are structured as follows: card_diamonds_1 with the child acard_diamonds_1 and this node’s child is cacard_diamonds_1, which is the CollisionArea2D node I’m trying to set the shape of.

i tried print(tempNode) and get something like /root/card_clubs_13/acard_clubs_13:<Area2D#29293020516>/cacard_clubs_13:<CollisionShape2D#29309797733>

could it bet the <Area2D#29293020516> and <CollisionShape2D#29309797733> that mess up the path since i do

	deckAreaNodes.append(str(cardArea2d))
	deckCollisionNodes.append(str(cardColission2d))

so i changed cardArea2d with AreaNodeName+deck[i] with

	deckAreaNodes.append(str(AreaNodeName+deck[i]))
	deckCollisionNodes.append(str(collisionNodeName+AreaNodeName+deck[i]))

and now print(tempNode) prints out

/root/card_clubs_13/acard_clubs_13/cacard_clubs_13

but when i add

	get_node(tempNode).shape = RectangleShape2D.new()

i get the same error as earlier

“error ‘Invalid set index “shape” (on base: “null instance”)’ with a value type of ‘RectangleShape2D.’”

Is your root node named “card_diamonds_1”? If so I think removing the “/root/” part of your path should work for referencing your node?

1 Like

the problem was that i have the all the nodes as a child of a node2D called board and since i had the path as

/root/cards…

it shuld have been

/root/board/cards…

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.