Files
Station-0/scripts/ui/hud.gd
T

207 lines
7.0 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
extends CanvasLayer
# ---------------------------------------------------------------------------
# Heart geometry — two polygons per slot: background (dark) + fill (red)
# ---------------------------------------------------------------------------
# Full heart, centered at origin, ~40 wide x 36 tall
var HEART_FULL := PackedVector2Array([
Vector2( 0, 18), Vector2(-15, 3), Vector2(-20, -6),
Vector2(-15, -15), Vector2(-6, -18), Vector2(-2, -14),
Vector2( 0, -11),
Vector2( 2, -14), Vector2( 6, -18), Vector2(15, -15),
Vector2( 20, -6), Vector2(15, 3),
])
# Left half only — used for the half-heart fill
var HEART_HALF := PackedVector2Array([
Vector2( 0, 18), Vector2(-15, 3), Vector2(-20, -6),
Vector2(-15, -15), Vector2(-6, -18), Vector2(-2, -14),
Vector2( 0, -11),
])
const FULL_COLOR := Color(0.90, 0.10, 0.10) # bright red
const EMPTY_COLOR := Color(0.18, 0.04, 0.04) # dark maroon (background)
const HEART_SPACING := 52 # px between heart centers
const ORIGIN := Vector2(32, 32) # center of first heart (screen px)
# ---------------------------------------------------------------------------
# DEPRECATED — Boss bar (commented out)
# ---------------------------------------------------------------------------
#const BOSS_BAR_W := 400.0
#const BOSS_BAR_H := 18.0
#const BOSS_BAR_POS := Vector2(760.0, 1040.0) # bottom center (1920×1080 viewport)
# ---------------------------------------------------------------------------
# State
# ---------------------------------------------------------------------------
# Each entry: { "bg": Polygon2D, "fill": Polygon2D }
var _slots: Array = []
var _credits_label: Label
# DEPRECATED — Boss bar nodes (commented out)
#var _boss_bar_root: Node2D = null
#var _boss_bar_fill: Polygon2D = null
#var _boss_bar_label: Label = null
#var _boss_max_hp: float = 1.0
# ---------------------------------------------------------------------------
# Boot
# ---------------------------------------------------------------------------
func _ready() -> void:
EventBus.player_health_changed.connect(_on_health_changed)
EventBus.credits_changed.connect(_on_credits_changed)
# DEPRECATED — Boss bar signal connections (commented out)
#EventBus.boss_health_changed.connect(_on_boss_health_changed)
#EventBus.boss_died.connect(_on_boss_died)
_build_credits_label()
# Initialise once the scene is fully set up
call_deferred("_init_from_player")
func _init_from_player() -> void:
var p = get_tree().get_first_node_in_group("player")
if p:
_rebuild(p.stats.max_health, p.stats.current_health)
else:
_rebuild(6.0, 6.0)
# ---------------------------------------------------------------------------
# Build / rebuild all heart slots
# ---------------------------------------------------------------------------
func _rebuild(max_hp: float, current_hp: float) -> void:
for slot in _slots:
slot["bg"].queue_free()
slot["fill"].queue_free()
_slots.clear()
var num_hearts := int(max_hp / 2.0)
for i in num_hearts:
var center := ORIGIN + Vector2(i * HEART_SPACING, 0)
# Background — always visible, shows the "empty" container
var bg := Polygon2D.new()
bg.polygon = HEART_FULL
bg.color = EMPTY_COLOR
bg.position = center
add_child(bg)
# Fill — overlaid on top; polygon shape changes per fill level
var fill := Polygon2D.new()
fill.polygon = HEART_FULL
fill.color = FULL_COLOR
fill.position = center
add_child(fill)
_slots.append({"bg": bg, "fill": fill})
_update_display(current_hp)
# ---------------------------------------------------------------------------
# Update fill polygons to reflect current health
# ---------------------------------------------------------------------------
func _update_display(current_hp: float) -> void:
for i in _slots.size():
var fill: Polygon2D = _slots[i]["fill"]
var hp_in_slot := current_hp - i * 2.0
if hp_in_slot >= 2.0:
fill.polygon = HEART_FULL
fill.visible = true
elif hp_in_slot >= 1.0:
fill.polygon = HEART_HALF
fill.visible = true
else:
fill.visible = false
# ---------------------------------------------------------------------------
# Credits label
# ---------------------------------------------------------------------------
func _build_credits_label() -> void:
_credits_label = Label.new()
_credits_label.position = Vector2(16, 72)
var amount := RunManager.run_credits if RunManager.run_active else UpgradeManager.wallet_credits
_credits_label.text = "SCRAP: %d" % amount
add_child(_credits_label)
func _on_credits_changed(new_total: int) -> void:
_credits_label.text = "SCRAP: %d" % new_total
# ---------------------------------------------------------------------------
# Signal handler
# ---------------------------------------------------------------------------
func _on_health_changed(current_hp: float, max_hp: float) -> void:
var num_hearts := int(max_hp / 2.0)
if num_hearts != _slots.size():
_rebuild(max_hp, current_hp)
else:
_update_display(current_hp)
# ---------------------------------------------------------------------------
# DEPRECATED — Boss health bar (commented out)
# ---------------------------------------------------------------------------
#var _boss_name: String = ""
#
#func _on_boss_health_changed(current_hp: float, max_hp: float, boss_name: String) -> void:
# if _boss_bar_root == null:
# _build_boss_bar(max_hp, boss_name)
# elif _boss_name != boss_name:
# # Different boss, update label
# _boss_name = boss_name
# if _boss_bar_label != null:
# _boss_bar_label.text = boss_name
# _boss_max_hp = max_hp
# _update_boss_bar(current_hp)
#
#func _on_boss_died() -> void:
# if _boss_bar_root != null:
# _boss_bar_root.queue_free()
# _boss_bar_root = null
# _boss_bar_fill = null
# _boss_bar_label = null
# _boss_name = ""
#
#func _build_boss_bar(max_hp: float, boss_name: String) -> void:
# _boss_max_hp = max_hp
# _boss_name = boss_name
#
# _boss_bar_root = Node2D.new()
# _boss_bar_root.position = BOSS_BAR_POS
# add_child(_boss_bar_root)
#
# # Name label
# _boss_bar_label = Label.new()
# _boss_bar_label.text = boss_name
# _boss_bar_label.position = Vector2(0, -22)
# _boss_bar_root.add_child(_boss_bar_label)
#
# # Background
# var bg := Polygon2D.new()
# bg.polygon = PackedVector2Array([
# Vector2(0, 0), Vector2(BOSS_BAR_W, 0),
# Vector2(BOSS_BAR_W, BOSS_BAR_H), Vector2(0, BOSS_BAR_H),
# ])
# bg.color = Color(0.15, 0.05, 0.05)
# _boss_bar_root.add_child(bg)
#
# # Fill
# _boss_bar_fill = Polygon2D.new()
# _boss_bar_fill.polygon = PackedVector2Array([
# Vector2(0, 0), Vector2(BOSS_BAR_W, 0),
# Vector2(BOSS_BAR_W, BOSS_BAR_H), Vector2(0, BOSS_BAR_H),
# ])
# _boss_bar_fill.color = Color(0.85, 0.1, 0.1)
# _boss_bar_root.add_child(_boss_bar_fill)
#
#func _update_boss_bar(current_hp: float) -> void:
# if _boss_bar_fill == null:
# return
# var pct := clampf(current_hp / _boss_max_hp, 0.0, 1.0)
# var w := BOSS_BAR_W * pct
# _boss_bar_fill.polygon = PackedVector2Array([
# Vector2(0, 0), Vector2(w, 0),
# Vector2(w, BOSS_BAR_H), Vector2(0, BOSS_BAR_H),
# ])