I am coding a star collect game in Godot, but while trying to add a scene as a child of the main (The scene which starts first, and the scene where I am doing the instancing), it's not working, rather the debug screen lags so much that it shows "Not Responding". I am coding in GDScript. Here's what I coded in the main scene to do the instancing:
extends Node2D
export (PackedScene) var Star
func _ready():
pass
func _on_Timer_timeout():
var star = Star.instance()
add_child(star)
I've also inserted the desired scene I want to instance in the Script variables section (Sorry, as I'm new to Godot I'm not able to explain the terms well) : Script Variables section
And this is the code of the scene which I am instancing:
extends Area2D
export var done = 0
export var speed = 43
export var spinVal = 0
export var dir = 0
func _ready():
done=0
dir=5-(randf()*10)
spinVal = 5-(randf()*10)
position.x=randf()*10
position.y=-20
while done==0:
position.y+=speed
rotation_degrees=0+dir
rotate(spinVal)
print(position)
func _on_VisibilityNotifier2D_screen_exited():
if (position.y<720):
done=1
queue_free()
Before, I had tried the simple way of instancing before I used PackedScene method, but I was facing the same problem. Now I'm trying it this way but no improvements...
Your instancing is fine. Your scene is wrong.
As soon as you add the instanced scene with add_child
, it's _ready
will run. And this:
func _ready():
done=0
dir=5-(randf()*10)
spinVal = 5-(randf()*10)
position.x=randf()*10
position.y=-20
while done==0:
position.y+=speed
rotation_degrees=0+dir
rotate(spinVal)
Well, that is is an infinite loop. The first line ensures done
is 0. And nothing in there will set done
to something else. The game is stuck there.
I see you set done
somewhere else:
func _on_VisibilityNotifier2D_screen_exited():
if (position.y<720):
done=1
queue_free()
Yet, that code never had a chance to run.
If you really, REALLY, want to write your motion in _ready
. You can do this:
func _ready():
done=0
dir=5-(randf()*10)
spinVal = 5-(randf()*10)
position.x=randf()*10
position.y=-20
while done==0:
yield(get_tree(), "physics_frame") # <--
position.y+=speed
rotation_degrees=0+dir
rotate(spinVal)
When the code reaches yield
, it will be suspended until the specified signal happens, then it continues. In this case the "physics_frame"
signal of the SceneTree
. I'm using "physics_frame"
instead of "idle_frame"
given that this is an Area2D
.
The more idiomatic way to write this is, of course:
extends Area2D
export var done = 0
export var speed = 43
export var spinVal = 0
export var dir = 0
func _ready():
done=0
dir=5-(randf()*10)
spinVal = 5-(randf()*10)
position.x=randf()*10
position.y=-20
func _physics_process(_delta):
if done != 0:
return
position.y+=speed
rotation_degrees=0+dir
rotate(spinVal)
func _on_VisibilityNotifier2D_screen_exited():
if (position.y<720):
done=1
queue_free()
In all honesty, I don't think you need done
at all. However, given it is an exported variable, I didn't remove it.
I'm not sure about your rotation either. But that is a separate issue.