Enemy Spawning and using their variables in main script

Could you paste your entire script in a code block? So we can read it easier?

Make it easier for new users to format and preview code in their posts - #4 by gertkeno

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)

1 Like

The main script:

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)
1 Like

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.

globallocal
Is this how you set something local? I did this but it seems to have applied to every scene, which I guess is fine idk.

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

1 Like

Here is the new main script,

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)
	
	

So I’m using the local variable correctly?

Yes Burger is a local variable in this script.

1 Like

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