Hello, I have been following a tutorial for top down shooter enemy ai, and have come across this error in the code in the main scene: Line 7:No constructor of “Callable” matches the signature “Callable(String, Node, String)”.
Here is the code for the main scene (level 1) where i got the error,
extends Node2D
@onready var bullet_manager = $bulletmanager
@onready var player = $player
func _ready() -> void:
GlobalSignals.connect(Callable("bullet_fired", bullet_manager, "handle_bullet_spawned"))
this is the code for the player:
extends CharacterBody2D
class_name Player
signal player_fired_bullet(bullet, position, direction)
@export var speed: float = 100
@export var accel: float = 10
@onready var weapon = $weapon
@onready var health_stat = $Health
@onready var anim_sprite: AnimatedSprite2D = $AnimatedSprite2D as AnimatedSprite2D
func _ready() -> void:
weapon.connect("weapon_fired", shoot)
func _physics_process(_delta: float) -> void:
var direction: Vector2 = Input.get_vector("move_left", "move_right", "move_up", "move_down")
velocity.x = move_toward(velocity.x, speed * direction.x, accel)
velocity.y = move_toward(velocity.y, speed * direction.y, accel)
look_at(get_global_mouse_position())
move_and_slide()
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("shoot"):
weapon.shoot()
func shoot(bullet_instance, location: Vector2, direction: Vector2):
emit_signal("player_fired_bullet", bullet_instance, location, direction)
func handle_hit():
health_stat.health -= 20
print('ouch!', health_stat.health)
this is the code for the enemy:
extends CharacterBody2D
@onready var health_stat = $Health
@onready var ai = $AI
@onready var weapon = $weapon
func _ready() -> void:
ai.initialize(self, weapon)
func handle_hit():
health_stat.health -= 20
if health_stat.health <= 0:
queue_free()
this is the code for the enemy AI:
extends Node2D
signal state_changed(new_state)
enum State {
PATROL,
ENGAGE
}
@onready var player_detection_zone = $playerdetectionzone
var current_state: int = State.PATROL : set = set_state
var actor = null
var player: Player = null
var weapon: Weapon = null
func _process(delta: float) -> void:
match current_state:
State.PATROL:
pass
State.ENGAGE:
if player != null and weapon != null:
actor.rotation = actor.global_position.direction_to(player.global_position).angle()
weapon.shoot()
else:
print('in the engage state but no weapon or player')
_:
print("ERROR: FOUND A STATE FOR OUR ENEMY THAT SHOULD NOT EXIST")
func initialize(actor, weapon: Weapon):
self.actor = actor
self.weapon = weapon
func set_state(new_state: int):
if new_state == current_state:
return
current_state = new_state
emit_signal("state_changed", current_state)
func _on_playerdetectionzone_body_entered(body: Node) -> void:
if body.is_in_group("player"):
set_state(State.ENGAGE)
player = body
here is the code for the bullet:
extends Area2D
class_name Bullet
@export var speed: int = 15
@onready var kill_timer = $killtimer
var direction := Vector2.ZERO
func _ready() -> void:
kill_timer.start()
func _physics_process(delta: float) -> void:
if direction != Vector2.ZERO:
var velocity = direction * speed
global_position += velocity
func set_direction(direction: Vector2):
self.direction = direction
rotation += direction.angle()
func _on_killtimer_timeout() -> void:
queue_free()
func _on_body_entered(body: Node) -> void:
if body.has_method("handle_hit"):
body.handle_hit()
queue_free()
here is the code for the bullet manager:
extends Node2D
func handle_bullet_spawned(bullet: Bullet, position: Vector2, direction: Vector2):
add_child(bullet)
bullet.global_position = position
bullet.set_direction(direction)
here is the code for the weapon:
extends Node2D
class_name Weapon
signal weapon_fired(bullet, location, direction)
@export var Bullet :PackedScene
@onready var end_of_gun = $endofgun
@onready var gun_direction = $gundirection
@onready var attack_cooldown = $attackcooldown
@onready var animation_player = $AnimationPlayer
# Called when the node enters the scene tree for the first time.
func shoot():
if attack_cooldown.is_stopped() and Bullet != null:
var bullet_instance = Bullet.instantiate()
var direction = (gun_direction.global_position - end_of_gun.global_position).normalized()
emit_signal("weapon_fired", bullet_instance, end_of_gun.global_position, direction)
attack_cooldown.start()
animation_player.play("muzzleflash")
here is the code for the GlobalSignals:
extends Node
signal bullet_fired(bullet, position, direction)
here is the code for the health:
extends Node2D
@export var health: int = 100 : set = _set_state, get = _get_state
func _set_state(new_health):
health = clamp(new_health, 0, 100)
func _get_state():
return health
here is the link to the tutorial i have been following:
the tutorial uses a version of godot 3, and i have been using godot 4. I have been changing some of the code for it to work in godot 4.
I would really appreciate some help, thank you!