Adding a child type Polygon2D from scripts with add_child() does nothing

Godot Version 4.2.1

Question

Hello. I’m trying to create a Polygon2D node from the script but it isn’t showing a thing.

image

#stage.gd
extends Node2D

var shape_floor = Shape.new()

func _ready():
	shape_floor.rect(300,300,200,200)
#shape.gd
class_name Shape
extends Node

#function to make rectangles
func rect(position_x: float, position_y: float, width: float, height: float) -> void:
	var v1 = Vector2()
	var v2 = Vector2()
	var v3 = Vector2()
	var v4 = Vector2()
	v1.x = position_x - width / 2
	v1.y = position_y - height / 2
	v2.x = position_x + width / 2
	v2.y = position_y - height / 2
	v3.x = position_x + width / 2
	v3.y = position_y + height / 2
	v4.x = position_x - width / 2
	v4.y = position_y + height / 2
	
	var vertices = PackedVector2Array()
	vertices.append(v1)
	vertices.append(v2)
	vertices.append(v3)
	vertices.append(v4)
	
	var polygon2d = Polygon2D.new()
	polygon2d.polygon = vertices
	polygon2d.color = Color(255, 0, 0, 255)
	add_child(polygon2d)

Thanks

im not sure if the shape_floor variable is referencing to this node or the Polygon2d?
i made 2 ways that will work to display it (at very least)

red one is method 1
green one is with method 2

the stage.gd code

extends Node2D
var shape_floor
var shape_floor2

# Called when the node enters the scene tree for the first time.
func _ready():
	#method1
	var temp=Shape.new()
	shape_floor=temp.rect(300,300,200,200)
	add_child(shape_floor)
	
	#method2
	var shape_floor2=Shape.new().rect2(500,500,100,200,self)

the shape.gd code

#shape.gd
class_name Shape
extends Node

#function to make rectangles
func rect(position_x: float, position_y: float, width: float, height: float) -> Polygon2D:
	var v1 = Vector2()
	var v2 = Vector2()
	var v3 = Vector2()
	var v4 = Vector2()
	v1.x = position_x - width / 2
	v1.y = position_y - height / 2
	v2.x = position_x + width / 2
	v2.y = position_y - height / 2
	v3.x = position_x + width / 2
	v3.y = position_y + height / 2
	v4.x = position_x - width / 2
	v4.y = position_y + height / 2
	
	var vertices = PackedVector2Array()
	vertices.append(v1)
	vertices.append(v2)
	vertices.append(v3)
	vertices.append(v4)
	
	var polygon2d = Polygon2D.new()
	polygon2d.polygon = vertices
	polygon2d.color = Color(255, 0, 0, 255)
	return polygon2d

func rect2(position_x: float, position_y: float, width: float, height: float,parent_node) -> Node:
	var v1 = Vector2()
	var v2 = Vector2()
	var v3 = Vector2()
	var v4 = Vector2()
	v1.x = position_x - width / 2
	v1.y = position_y - height / 2
	v2.x = position_x + width / 2
	v2.y = position_y - height / 2
	v3.x = position_x + width / 2
	v3.y = position_y + height / 2
	v4.x = position_x - width / 2
	v4.y = position_y + height / 2
	
	var vertices = PackedVector2Array()
	vertices.append(v1)
	vertices.append(v2)
	vertices.append(v3)
	vertices.append(v4)
	
	var polygon2d = Polygon2D.new()
	polygon2d.polygon = vertices
	polygon2d.color = Color(0, 1, 0, 1)
	parent_node.add_child(polygon2d)
	return self

the 3rd method will be make the Shape become a Scene. then just instantiate() it and set its initial rect value

1 Like

Nice, the method 2 is what I was looking for.
There’s only 1 thing I’d want to improve. I’d like the 5th argument “self” to be a default but I can’t achieve it.

//func declaration
func rectangle(position_x: float, position_y: float, width: float, height: float, node = self):
//func call
geometry.rectangle(300,300,200,200)

you want the parent node to be this node itself?

if you noticed, the parent to be added child will need it from outside the node, not this Node of Shape, else it will not be shown

1 Like

No, what I want the function call to adds the self argument by default. So I don’t need to write it

then it’s _init’s job

I don’t get it…
When I use the default 5th argument “node = self”, the function is not receiving the correct node as it does when I specify self as 5th argument in the function calling.

but it will still need to do something like
Shape.new(self) to create the Shape
but the rect method will stay with 4 parameters

the stage.gd code

extends Node2D

var shape_floor
var shape_floor2

# Called when the node enters the scene tree for the first time.
func _ready():
	##method1
	#var temp=Shape.new()
	#shape_floor=temp.rect(300,300,200,200)
	#add_child(shape_floor)
	
	#method2
	var shape_floor2=Shape.new(self).rect2(500,500,100,200)

the shape.gd code:

#shape.gd
class_name Shape
extends Node

var the_parent_node
func _init(parent):
	the_parent_node=parent

#function to make rectangles
func rect(position_x: float, position_y: float, width: float, height: float) -> Polygon2D:
	var v1 = Vector2()
	var v2 = Vector2()
	var v3 = Vector2()
	var v4 = Vector2()
	v1.x = position_x - width / 2
	v1.y = position_y - height / 2
	v2.x = position_x + width / 2
	v2.y = position_y - height / 2
	v3.x = position_x + width / 2
	v3.y = position_y + height / 2
	v4.x = position_x - width / 2
	v4.y = position_y + height / 2
	
	var vertices = PackedVector2Array()
	vertices.append(v1)
	vertices.append(v2)
	vertices.append(v3)
	vertices.append(v4)
	
	var polygon2d = Polygon2D.new()
	polygon2d.polygon = vertices
	polygon2d.color = Color(255, 0, 0, 255)
	return polygon2d

func rect2(position_x: float, position_y: float, width: float, height: float) -> Node:
	var v1 = Vector2()
	var v2 = Vector2()
	var v3 = Vector2()
	var v4 = Vector2()
	v1.x = position_x - width / 2
	v1.y = position_y - height / 2
	v2.x = position_x + width / 2
	v2.y = position_y - height / 2
	v3.x = position_x + width / 2
	v3.y = position_y + height / 2
	v4.x = position_x - width / 2
	v4.y = position_y + height / 2
	
	var vertices = PackedVector2Array()
	vertices.append(v1)
	vertices.append(v2)
	vertices.append(v3)
	vertices.append(v4)
	
	var polygon2d = Polygon2D.new()
	polygon2d.polygon = vertices
	polygon2d.color = Color(0, 1, 0, 1)
	the_parent_node.add_child(polygon2d)
	return self

Isn’t there a way to avoid using the “self” in any form when calling the function? some way to make the function to receive the node without having to send it manually…

something like:

func my_function(node = self_of_the_node_that_is_using_this_function)

use signal then, emit the signal for the parent to add this node as a child

or a group, so just get the parent node with the groupname, and use it to add child, so no need to assign it like this

mmm. that sounds like more trouble than using the self as argument…
What about sending by default the node path instead of the node itself? could it be set as default that way?
I mean, my ideal is to make the calling function as clean as possible and intuitive tu use to make custom shapes

Nevermind. I’m going with the _init(parent) solution.
Thanks

the problem here, the Shape script is not attached to any node, despite it extends from Node. So you dont really can do much with it, anything with this has to be initialized by .new() like an object or RefCounted do, or need to attached the Shape.gd to a real node from code.

the real solution i believe is to make the a Shape Scene, with its root Node being a Node or Node2d, and the child polygon2d is created from code . the Shape Scene with its root node attached with shape.gd will be instantiated and added child on stage Node first before you call .rect methods

another solution is to make this Shape.gd as an Autoload
so you can call it anywhere and it’s alrdy instantiated as a node when the game began
it really all depends how you wanted it to be

also to create multiple shape, you just need to call the rect2 method, dont need to .new(self) for every new shape
this will need you to save the reference of this newly create Shape.new(self) to a Variable first, then for every new shape you want to create, just call this variable.rect2()

I am trying to avoid the use of scenes or autoloads or anything that involves the godot GUI usage. I want this functions to be very portable and use it on every project just by adding this script with no need of configuring anything else.

Yes, the rect2 method you give me is pretty much what I want. It is just a little less intuitive when instantiating the object as it asks you for the self argument.

it’s now only need to assign it the first time at .new(self), so it should be okay