Ostatnio pisaliśmy o tym jak stworzyć system zdrowia gracza w Godot. Dziś zajmiemy się konkretnie paskiem życia.
Pasek życia nad przeciwnikiem to prosty element interfejsu, który bardzo poprawia czytelność gry. Gracz od razu widzi, czy jego ataki działają, ile zdrowia zostało przeciwnikowi i czy warto kontynuować walkę.
W Godot 4 taki pasek można zrobić na kilka sposobów. W grze 2D najprościej dodać do przeciwnika node ProgressBar albo przygotować osobną scenę interfejsu zdrowia. W tym przykładzie użyjemy prostego rozwiązania, czyli paska życia jako dziecka przeciwnika.

Przykładowa struktura sceny przeciwnika
Enemy (CharacterBody2D)
├── Sprite2D
├── CollisionShape2D
├── HealthComponent
└── HealthBar (ProgressBar)
HealthComponent odpowiada za przechowywanie zdrowia, a HealthBar wyświetla aktualny stan HP. Dzięki temu logika i wygląd są od siebie oddzielone.
Skrypt komponentu zdrowia
Jeżeli korzystasz już z komponentu zdrowia z poprzedniego artykułu, możesz użyć go także u przeciwnika. Przykład:
extends Node
signal health_changed(current_health: int, max_health: int)
signal died
@export var max_health: int = 50
var current_health: int = 0
var is_dead: bool = false
func _ready() -> void:
current_health = max_health
health_changed.emit(current_health, max_health)
func take_damage(amount: int) -> void:
if is_dead:
return
current_health -= amount
current_health = clamp(current_health, 0, max_health)
health_changed.emit(current_health, max_health)
if current_health <= 0:
is_dead = true
died.emit()
Skrypt przeciwnika
Teraz trzeba połączyć przeciwnika z paskiem życia. Skrypt przeciwnika może wyglądać tak:
extends CharacterBody2D
@onready var health_component: Node = $HealthComponent
@onready var health_bar: ProgressBar = $HealthBar
func _ready() -> void:
health_component.health_changed.connect(_on_health_changed)
health_component.died.connect(_on_died)
health_bar.visible = false
func _on_health_changed(current_health: int, max_health: int) -> void:
health_bar.max_value = max_health
health_bar.value = current_health
health_bar.visible = current_health < max_health
func _on_died() -> void:
queue_free()
Dlaczego pasek życia jest ukryty na początku?
W powyższym przykładzie pasek życia jest ukrywany, gdy przeciwnik ma pełne zdrowie. To bardzo popularne rozwiązanie, ponieważ ekran nie jest wtedy przeładowany dodatkowymi elementami GUI.
Pasek pojawia się dopiero wtedy, gdy przeciwnik otrzyma pierwsze obrażenia. Dzięki temu gracz dostaje informację dokładnie wtedy, kiedy jest ona potrzebna.
Jak ustawić pasek nad przeciwnikiem?
Jeżeli HealthBar jest dzieckiem przeciwnika, wystarczy przesunąć go w edytorze nad sprite przeciwnika. W przypadku gry 2D można ustawić jego pozycję na przykład tak:
HealthBar position:
x = -30
y = -45
Warto dopasować szerokość paska do rozmiaru przeciwnika. Mały przeciwnik nie powinien mieć ogromnego paska HP, bo będzie wyglądać nienaturalnie.
Przykład zadania obrażeń przeciwnikowi
Do testu można dodać prostą funkcję w skrypcie przeciwnika:
func test_damage() -> void:
health_component.take_damage(10)
Można ją wywołać z ataku gracza, pocisku albo tymczasowo z klawisza testowego.
Najczęstsze błędy
- brak połączenia sygnału
health_changed, - zła ścieżka do node’a
HealthBar, - pasek życia jest za duży albo za daleko od przeciwnika,
- wartość
max_valuenie jest ustawiana, - pasek nie znika po śmierci przeciwnika.
Podsumowanie
Pasek życia nad przeciwnikiem to prosty, ale bardzo przydatny element gry. Najlepiej połączyć go z komponentem zdrowia przez sygnały. Dzięki temu pasek automatycznie reaguje na obrażenia, leczenie i śmierć przeciwnika.
inne artykuły o Health bar:
https://gameidea.org/2024/12/13/making-a-health-bar-and-health-system-in-godot/