Hello, i have been working on a top down shooter and I have been trying to implement a scoring system, but when I put the canvas layer node on for the ui, in the main game, the player can no longer shoot, here is the code:
Here is the code for the hud which is attached to a control node which is a child to a canvas layer node:
extends Control
@onready var score = $score:
set(value):
score.text = "Score: " + str(value)
Here is the code for the main game:
extends Node2D
@onready var bullet_manager = $bulletmanager
@onready var player = $player
@onready var enemy = $enemy
@onready var hud = $UIlayer/hud
var score: int = 0:
set(value):
score = value
hud.score = score
func _ready() -> void:
score = 0
randomize()
GlobalSignals.bullet_fired.connect(bullet_manager.handle_bullet_spawned)
enemy.killed.connect(_on_enemy_killed)
func _on_enemy_killed(points):
score += points
print(score)
here is the code for the player:
extends CharacterBody2D
class_name Player
@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 _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 handle_hit():
health_stat.health -= 20
print('ouch!', health_stat.health)
here is the code for the weapon that is used by the player and enemy:
extends Node2D
class_name Weapon
@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()
GlobalSignals.emit_signal("bullet_fired", bullet_instance, end_of_gun.global_position, direction)
attack_cooldown.start()
animation_player.play("muzzleflash")
here is the code for the enemy
extends CharacterBody2D
signal killed(points)
@onready var health_stat = $Health
@onready var ai = $AI
@onready var weapon = $weapon
@export var speed: int = 100
@export var points: int = 100
func _ready() -> void:
ai.initialize(self, weapon)
func rotate_toward(location: Vector2):
rotation = lerp(rotation, global_position.direction_to(location).angle(), 0.1)
func velocity_toward(location: Vector2) -> Vector2:
return global_position.direction_to(location) * speed
func handle_hit():
health_stat.health -= 20
if health_stat.health <= 0:
killed.emit(points)
queue_free()
here is the code for the bullet:
extends CharacterBody2D
signal killed(points)
@onready var health_stat = $Health
@onready var ai = $AI
@onready var weapon = $weapon
@export var speed: int = 100
@export var points: int = 100
func _ready() -> void:
ai.initialize(self, weapon)
func rotate_toward(location: Vector2):
rotation = lerp(rotation, global_position.direction_to(location).angle(), 0.1)
func velocity_toward(location: Vector2) -> Vector2:
return global_position.direction_to(location) * speed
func handle_hit():
health_stat.health -= 20
if health_stat.health <= 0:
killed.emit(points)
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 enemy ai:
extends Node2D
signal state_changed(new_state)
enum State {
PATROL,
ENGAGE
}
@onready var player_detection_zone = $playerdetectionzone
@onready var patrol_timer = $patroltimer
var current_state: int = -1 : set = set_state
var actor: CharacterBody2D = null
var player: Player = null
var weapon: Weapon = null
var origin: Vector2 = Vector2.ZERO
var patrol_location: Vector2 = Vector2.ZERO
var patrol_location_reached := false
var actor_velocity: Vector2 = Vector2.ZERO
func _ready() -> void:
set_state(State.PATROL)
func _process(delta: float) -> void:
match current_state:
State.PATROL:
if not patrol_location_reached:
actor.rotation = lerp(actor.rotation, actor.global_position.direction_to(patrol_location).angle(), 0.1)
actor.velocity = actor_velocity
actor.move_and_slide()
actor.rotate_toward(patrol_location)
if actor.global_position.distance_to(patrol_location) < 5:
patrol_location_reached = true
actor_velocity = Vector2.ZERO
patrol_timer.start()
State.ENGAGE:
if player != null and weapon != null:
var angle_to_player = actor.global_position.direction_to(player.global_position).angle()
actor.rotate_toward(player.global_position)
if abs(actor.rotation - angle_to_player) < 0.1:
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
if new_state == State.PATROL:
origin = global_position
patrol_timer.start()
patrol_location_reached = true
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
func _on_playerdetectionzone_body_exited(body) -> void:
if player and body == player:
set_state(State.PATROL)
player = null
func _on_patroltimer_timeout() -> void:
var patrol_range = 50
var random_x = randf_range(-patrol_range, patrol_range)
var random_y = randf_range(-patrol_range, patrol_range)
patrol_location = Vector2(random_x, random_y) + origin
patrol_location_reached = false
actor_velocity = actor.velocity_toward(patrol_location)
here is the code for the health that can be used for the player and the enemy:
@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 code for the global signals:
extends Node
signal bullet_fired(bullet, position, direction)
I am using godot 4.2.2
here is the tutorial I have been following: https://www.youtube.com/watch?v=6JGKvJbkTWA
Help would be much appreciated, thank you!