Just one enemy instance shoot

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Shortanel

Hey there I have a problem with my project. I created a spawner for my enemy that spawn them every second and when they are added in the scene they shoot a “bullet”(they are flies in a space shooter ) but just the first instacieted fly shoot the rest of them don’t. This is the code:

Fly:

extends Area2D

export var health = 3
export var speed = 100
export var fire_rate = 1
var fire_rate_timer = Timer.new()

func _ready():
	$Skin.play()
#set the timer for the fire rate
	set_timer()

func _process(delta):
#moving by itself to the left side of the screen
	#global_position.x -= speed * delta
#elimate if it's out of the screen
	if global_position.x < -10:
		queue_free()
#shoot
	if Global.fly_can_shoot == true :
		Methods.play_sound("Shoot")
		EventBus.emit_signal("create_fly_projectile",Global.Fly_projectile,global_position)
		Global.fly_can_shoot = false
		fire_rate_timer.start()
		print("shoot")

func _on_Fly_area_entered(_area):
		health -= 1
		check_health()

func on_shoot_timeout():
	Global.fly_can_shoot =true

func set_timer():
	fire_rate_timer.set_one_shot(true)
	fire_rate_timer.set_wait_time(fire_rate)
	fire_rate_timer.connect("timeout",self,"on_shoot_timeout")
	add_child(fire_rate_timer)

func check_health(): 
	#check if enemy he still has health
	if health <= 0:
		Methods.play_sound("Explosion")
		EventBus.emit_signal("create_explosion",Global.Explosion,global_position)
		queue_free()  
	else:
		Methods.play_sound("Hit")

Fly_projectile:

extends Area2D

func _process(delta):
#moving by itself to the left side of the screen
	global_position.x -= Global.enemies_projectiles["fly_projectile"]["speed"] *delta
#elimate if it's out of the screen
	if global_position.x < -10:
		queue_free()

func _on_Fly_Projectile_area_entered(_area):
	queue_free()

fly_spawner:

extends Timer

export (PackedScene)var Fly
#make an instance of a fly in the boundray of screen
func _on_fly_timeout():
	randomize()
	var fly = Fly.instance()
	get_parent().add_child(fly)
	fly.global_position.x = 328
	fly.global_position.y = rand_range(8,172)

Singletons:

Global:

extends Node

var enemies = {
	
	"asteroid":{
		"health" : 1,
		"damage" : 1,
		"points" : 5,
		"speed" : 100},
	"fly":{
		"health":3,
		"damage":1,
		"points":10,
		"speed": 100,}
}

var player = {
	"health": 4,
	"damage": 1,
	"speed": 110
}

var star_type ={
	"big":50,
	"small":60
}

var player_lasers = {
	"blue":{
			"damage": 1,
			"speed": 150,
			"fire_rate":0.25
	}
}

var enemies_projectiles = {
	"fly_projectile":{
		"damage":1,
		"speed": 120,
		"fire_rate":3}
}

var World = null
var Asteroid = null
var Player = null
var Fly = null
var Sound_controller = null

var big_layer 
var small_layer 

var reset = false
var pause = false
var hit = false
var player_can_shoot = true
var fly_can_shoot = true

var score = 0
var player_health = player["health"]

var player_velocity = Vector2()

var Explosion = preload("res://Scene/VFX/Explosion.tscn")
var Laser = preload("res://Scene/VFX/Laser.tscn")
var Fly_projectile = preload("res://Scene/VFX/Fly_projectile.tscn")

const screen_width = 320
const screen_height = 180

Methods:

extends Node

func _ready():
	EventBus.connect("create_explosion",self,"create_explosion")
	EventBus.connect("create_laser",self,"create_laser")
	EventBus.connect("create_fly_projectile",self,"create_fly_projectile")

func play_sound(sound):
	if Global.Sound_controller != null:
		if Global.Sound_controller.has_node(sound):
			Global.Sound_controller.get_node(sound).play()

func game_over(reset):
		if reset:
			get_tree().reload_current_scene()
			Global.score = 0
			Global.reset = false

func pause():
	get_tree().change_scene("res://Scene/UI/Title_screen.tscn")

func star_motion(delta):
		Global.big_layer.motion_offset.x -= Global.star_type["big"] * delta
		Global.small_layer.motion_offset.x -= Global.star_type["small"] * delta

func create_explosion(explosion, location):
	var explosion_instance = explosion.instance()
	get_parent().add_child(explosion_instance)
	explosion_instance.global_position = location

func create_laser(laser, location):
	for i in range(1,4):
		var laser_instance_i = laser.instance()
		get_parent().add_child(laser_instance_i)
		match i:
			1:
				laser_instance_i.global_position = location + Vector2(11,-4)
			2:
				laser_instance_i.global_position = location + Vector2(13,0)
			3:
				laser_instance_i.global_position = location + Vector2(11,4)

func create_fly_projectile(projectile,location):
	var projectile_instance = projectile.instance()
	add_child(projectile_instance)
	projectile_instance.global_position = location + Vector2(-10,0)
	print("made")

func create_transition(transition,location):
	var transition_instance = transition.instance()
	get_parent().add_child(transition_instance)

Eventbus:

extends Node

signal score()
signal create_explosion(explosion,location)
signal create_laser(laser,location)
signal create_fly_projectile(projectile,location)
signal transmit_health(health)

any ideas?

:bust_in_silhouette: Reply From: exuin

So it looks like every single fly’s shooting is controlled by the same global variable? After the first fly shoots, that variable is set to false, so only the first fly can shoot. Don’t use a global variable to control it, use a local variable.

Thanks it works. But there is no way to make that with a global variable? I ask this for the future because I think if I work with global variables it will make my life easier.

Shortanel | 2021-04-26 12:30

I am not sure what you want to do with the fly shooting. Can you explain to me?

exuin | 2021-04-26 12:31

Yeah never mind now I understand how that supposed to work. The main reason I asked that is because I worked with global dictionaries, methods and signals and right I don’t use pretty much of them because of the many bugs and crashes that i get and that bugs me.
The tutorials make a general idea about singleton and globaly integrations but most of them is hard for me to understand and implement. Sorry for ranting about that and for the bad english and thanks again for the help.

Shortanel | 2021-04-26 12:45

:bust_in_silhouette: Reply From: Mougenot

Your fly_can_shoot applies to all Fly instances, but gets set to false in your _process() after 1 Fly shoots. I would suggest moving var fly_can_shoot = true out of Global and into Fly and changing all occurences of Global.fly_can_shoot to fly_can_shoot. This way each Fly instance has its own fly_can_shoot variable to modify and keep track of.

Fly:

extends Area2D

export var health = 3
export var speed = 100
export var fire_rate = 1
var fire_rate_timer = Timer.new()
var fly_can_shoot = true

func _ready():
    $Skin.play()
#set the timer for the fire rate
    set_timer()

func _process(delta):
#moving by itself to the left side of the screen
    #global_position.x -= speed * delta
#elimate if it's out of the screen
    if global_position.x < -10:
        queue_free()
#shoot
    if fly_can_shoot:
        Methods.play_sound("Shoot")
        EventBus.emit_signal("create_fly_projectile",Global.Fly_projectile,global_position)
        fly_can_shoot = false
        fire_rate_timer.start()
        print("shoot")

func _on_Fly_area_entered(_area):
        health -= 1
        check_health()

func on_shoot_timeout():
    fly_can_shoot =true

func set_timer():
    fire_rate_timer.set_one_shot(true)
    fire_rate_timer.set_wait_time(fire_rate)
    fire_rate_timer.connect("timeout",self,"on_shoot_timeout")
    add_child(fire_rate_timer)

func check_health(): 
    #check if enemy he still has health
    if health <= 0:
        Methods.play_sound("Explosion")
        EventBus.emit_signal("create_explosion",Global.Explosion,global_position)
        queue_free()  
    else:
        Methods.play_sound("Hit")