I’m not sure that set_deferred (two rs, not two fs) is what you need since queue_free is already a deferred operation. set or call deferred waits till the end of the frame to perform the operation, be it calling a function via call_deferred(callable) or setting a value via set_deferred(proper_name, new_value)
extends Node2D
var flyfood = false
const food = preload("res://cheese_burger.tscn")
var Burger
var enemy_count = 0
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
pass
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
spawn_food(delta)
if enemy_count == 0:
enemy_count = (enemy_count + 1)
Burger = food.instantiate()
Burger.position = $FoodSpawnSpotOne.position
self.add_child(Burger)
if Burger.eaten == true:
Burger.set_deferred()
if Burger.notbeingpunched == false and $JeansCat.punching == true:
flyfood = true
if flyfood == true and $JeansCat.arm_dir == true and Burger.dying_left == false:
Burger.die_right(delta)
if flyfood == true and $JeansCat.arm_dir == false and Burger.dying_right == false:
Burger.die_left(delta)
if Burger.readytorespawn == true:
enemy_count = 0
func spawn_food(delta):
pass
enemy code:
extends CharacterBody2D
static var FoodSPEED = 200
static var Foodirection = 1
var notbeingpunched = true
var infinity = 1.0 / 0.0
var dying_right = false
var dying_left = false
var readytorespawn = false
var eaten = false
func _ready():
var skin = randi_range(0, 1)
match skin:
0:
$AnimatedSprite2D.play("Burg")
1:
$AnimatedSprite2D.play("Fry")
func _physics_process(delta):
if notbeingpunched == true:
velocity.x = Foodirection * -FoodSPEED
if dying_right == true:
velocity.x = Foodirection * FoodSPEED + 720
$AnimatedSprite2D.rotation = move_toward($AnimatedSprite2D.rotation, infinity, 75 * delta)
$TimeToDie.start()
if dying_left == true:
velocity.x = Foodirection * -FoodSPEED + -720
$AnimatedSprite2D.rotation = move_toward($AnimatedSprite2D.rotation, infinity, 75 * delta)
$TimeToDie.start()
move_and_slide()
func _on_area_2d_area_entered(area: Area2D) -> void:
if area.is_in_group("Player"):
eaten = true
if area.is_in_group("Attack"):
notbeingpunched = false
func die_right(delta):
dying_right = true
func die_left(delta):
dying_left = true
velocity.x = Foodirection * -FoodSPEED + -720
$AnimatedSprite2D.rotation = move_toward($AnimatedSprite2D.rotation, infinity, 75 * delta)
$TimeToDie.start()
func _on_time_to_die_timeout():
$".".queue_free()
readytorespawn = true
func _on_area_2d_area_exited(area):
if area.is_in_group("Attack") and dying_right == false and dying_left == false:
notbeingpunched = true
queue_free() will destroy the enemy object at the end of the frame, setting readytorespawn is frivilous; to work with queue_free you must change a couple other ways you handle this enemy. You cannot guarentee it will exist so other scripts should avoid referencing it for extended periods, i.e. your Burger variable.
I’m assuming this is a collision detection, let’s move it to the enemy’s script instead. And when the enemy spawns you can give them the Player’s node to store, since the player will exist for the game’s length or at least longer than enemies exist.
var player
if notbeingpunched == false and player.punching == true:
flyfood = true
if flyfood and player.arm_dir == true and dying_left == false:
dying_right = true
if flyfood and player.arm_dir == false and dying_right == false:
dying_left = true
For spawning let’s make Burger local, so it only exists during spawning, then connect a function to when the enemy is exiting the tree, aka despawning.
func enemy_despawn() -> void:
enemy_count -= 1
func _process(delta: float) -> void:
if enemy_count == 0:
enemy_count += 1
var Burger = food.instantiate() # declared locally here
Burger.position = $FoodSpawnSpotOne.position
# calls enemy_despawn when despawn
Burger.exiting_tree.connect(enemy_despawn)
self.add_child(Burger)
Thanks a lot! I don’t think I knew anything about how to handle other scripts connecting with each other unless it was with the main script, so this helped a ton, and now the enemy’s code just handles all of that.
A “local” variable is one that only exists within a function body, not a class body.
extends Node2D
var burger: Node2D # global variable, defined in class body
func test1() -> void:
burger = $Burger # editing global
var burger_local: Node2D # local variable, defined in function test1
burger_local = $Burger # editing local
func test2() -> void:
print(burger) # using global, works
print(burger_local) # does not work, burger_local defined only in test1
Essentially the only change I made to make your Burger local was adding var to it here
extends Node2D
var flyfood = false
const food = preload("res://cheese_burger.tscn")
static var score = 0
static var R_enemy_count = 0
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
pass
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
spawn_food(delta)
if R_enemy_count < 10:
R_enemy_count = (R_enemy_count + 1)
var Burger = food.instantiate()
Burger.position = $FoodSpawnSpotOne.position
self.add_child(Burger)