Hi! I’ve done some modifications in my code in regards to your advice, also I’m no longer trying to connect them directly, because I’m just realizing that the point of a good composition is the ability to implement and remove parts with minimal errors and effort, and connecting the Health component to the HealthBar took away from that freedom, so I’ve connected them inside the Player script, trying to leave them modular.
In a way I have succeeded, the Progress Bar “Health” now responds to changes in health, be they positive (heal) or negative (hurt) but I’ve run into two problems.
1.-The Progress Bar “DamageBar” does not respond to the timer I’ve put, updating in a frame instead of seconds.
2.-If the value of “health.maxHP” is greater than the value of “health_bar.max_value” my ProgressBar “HealthBar” remains in its maximum value without updating, so I get a healthbar that does not move until the current health goes below the “health_bar.max_value”
Here is my code for Health component
class_name Health extends Node
signal changed(current : float , max : float)
signal died
@export var maxHP: float
@export var body: CharacterBody3D
@export var model: Node3D
var current: float
func _ready():
current = maxHP
_emit()
func damage(amount : float):
current = clamp(current - amount , 0.0 , maxHP)
_emit()
if current == 0.0:
died.emit()
func heal(amount : float):
current= clamp(current + amount , 0.0 , maxHP)
_emit()
func _emit() -> void:
changed.emit(current,maxHP)
print("HP %d / %d" % [current,maxHP])
Here is my code for Healthbar
extends ProgressBar
@onready var timer = $Timer
@onready var damagebar = $DamageBar
var health = 0 : set = set_health
func set_health(new_health):
var prev_health = health
health = min(max_value,new_health)
value = health
if health < prev_health:
timer.start()
else:
damagebar.value = health
func init_healt(_health):
health = _health
max_value = _health
value = health
damagebar.max_value = health
damagebar.value = health
func new_max_health_range(new_max_health:float):
max_value = new_max_health
func _on_timer_timeout():
damagebar.value = health
and here is my code for the player.
class_name Player extends CharacterBody3D
@onready var innput = $input
@onready var movement = $Movement
@onready var jump = $Jump
@onready var health = $Health
@onready var health_bar = $CanvasLayer/HealthBar
func _ready() -> void:
health.died.connect(_on_died)
health_bar.health = health.maxHP
func _physics_process(delta: float) -> void:
innput._update()
movement.direction = innput.move_dir
movement.tick(delta)
jump.wants_to_jump = innput.jump_is_pressed
jump.wants_to_stop_jump = innput.jump_is_released
jump.tick(delta)
health_bar.health = health.current
if innput.hurt_is_pressed:
health.damage(25)
if innput.heal_is_pressed:
health.heal(25)
if position.y <= -10.0:
health.current = 0
_on_died()
func _on_died() -> void:
print("Game Over!")
get_tree().reload_current_scene()