Files
Bullosseum/hud.gd
T

380 lines
12 KiB
GDScript

extends CanvasLayer
const _GOLD := Color(1.00, 0.78, 0.22)
const _CREAM := Color(0.88, 0.83, 0.72)
const _MUTED := Color(0.65, 0.60, 0.48)
const _BG := Color(0.06, 0.04, 0.02, 0.78)
const _BADGE := Color(0.16, 0.10, 0.03, 0.90)
const _BORDER := Color(0.65, 0.48, 0.15, 0.55)
const _ABILITY_ICONS: Array[String] = [
"res://HUD/HUD_0000_ability_JALG.png",
"res://HUD/HUD_0001_ability_SLAM.png",
"res://HUD/HUD_0002_ability_DASH.png",
]
const _ABILITY_ACTIONS: Array[StringName] = [&"ability_kick", &"ability_slam", &"ability_dash"]
var _controls_visible: bool = true
var _controls_panel: PanelContainer
var _toggle_btn: Button
var _spawner: Node
var _player: Node = null
var _cd_overlays: Array[ColorRect] = []
var _cd_labels: Array[Label] = []
var _health_segments: Array[ColorRect] = []
var _health_connected: bool = false
func _ready() -> void:
layer = 11
process_mode = Node.PROCESS_MODE_ALWAYS
_build_controls_panel()
_build_ability_bar()
_build_health_bar()
_find_spawner.call_deferred()
func _process(_delta: float) -> void:
if _player == null:
var players := get_tree().get_nodes_in_group(&"player")
if not players.is_empty():
_player = players[0]
return
if not _health_connected:
_health_connected = true
_player.health_changed.connect(_on_health_changed)
_on_health_changed(_player.health)
for i: int in _cd_overlays.size():
var fraction: float = _player.call(&"ability_cooldown_fraction", i)
var ov := _cd_overlays[i]
ov.anchor_top = 1.0 - fraction
ov.anchor_bottom = 1.0
var remaining: float = _player.call(&"ability_cooldown_remaining", i)
var lbl := _cd_labels[i]
if remaining > 0.0:
lbl.text = "%.1fs" % remaining
lbl.visible = true
else:
lbl.visible = false
func _find_spawner() -> void:
var spawners := get_tree().get_nodes_in_group(&"matador_spawn")
if not spawners.is_empty():
_spawner = spawners[0]
func _unhandled_input(event: InputEvent) -> void:
if event is InputEventKey and event.pressed and not event.echo:
if event.physical_keycode == KEY_TAB:
_toggle_controls()
elif event.physical_keycode == KEY_ESCAPE:
_return_to_menu()
func _return_to_menu() -> void:
get_tree().paused = false
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
get_tree().change_scene_to_file("res://MainMenu.tscn")
func _toggle_controls() -> void:
_controls_visible = not _controls_visible
_controls_panel.visible = _controls_visible
_toggle_btn.text = "Hide controls" if _controls_visible else "Show controls"
func _on_reset_pressed() -> void:
if get_tree().paused:
get_tree().paused = false
if _spawner:
_spawner.reset_spawn()
func _build_health_bar() -> void:
var bar := HBoxContainer.new()
bar.add_theme_constant_override("separation", 4)
bar.anchor_left = 0.5
bar.anchor_right = 0.5
bar.anchor_top = 0.0
bar.anchor_bottom = 0.0
bar.grow_horizontal = Control.GROW_DIRECTION_BOTH
bar.offset_left = -90.0
bar.offset_top = 16.0
bar.offset_bottom = 16.0
add_child(bar)
var bg_style := StyleBoxFlat.new()
bg_style.bg_color = _BG
bg_style.corner_radius_top_left = 4
bg_style.corner_radius_top_right = 4
bg_style.corner_radius_bottom_left = 4
bg_style.corner_radius_bottom_right = 4
bg_style.border_width_left = 1
bg_style.border_width_right = 1
bg_style.border_width_top = 1
bg_style.border_width_bottom = 1
bg_style.border_color = _BORDER
bg_style.content_margin_left = 6.0
bg_style.content_margin_right = 6.0
bg_style.content_margin_top = 6.0
bg_style.content_margin_bottom = 6.0
var panel := PanelContainer.new()
panel.add_theme_stylebox_override("panel", bg_style)
bar.add_child(panel)
var inner := HBoxContainer.new()
inner.add_theme_constant_override("separation", 3)
panel.add_child(inner)
for i: int in 10:
var seg := ColorRect.new()
seg.custom_minimum_size = Vector2(14.0, 14.0)
seg.color = Color(0.72, 0.08, 0.08)
inner.add_child(seg)
_health_segments.append(seg)
func _on_health_changed(new_health: int) -> void:
for i: int in _health_segments.size():
_health_segments[i].color = Color(0.72, 0.08, 0.08) if i < new_health \
else Color(0.20, 0.10, 0.10)
func _build_ability_bar() -> void:
var bar := HBoxContainer.new()
bar.add_theme_constant_override("separation", 10)
bar.anchor_left = 0.5
bar.anchor_right = 0.5
bar.anchor_top = 1.0
bar.anchor_bottom = 1.0
bar.grow_horizontal = Control.GROW_DIRECTION_BOTH
bar.grow_vertical = Control.GROW_DIRECTION_BEGIN
bar.offset_left = -120.0
bar.offset_bottom = -20.0
add_child(bar)
for i: int in 3:
bar.add_child(_build_ability_slot(i))
func _build_ability_slot(idx: int) -> Control:
var vbox := VBoxContainer.new()
vbox.add_theme_constant_override("separation", 4)
var bg_style := StyleBoxFlat.new()
bg_style.bg_color = _BG
bg_style.corner_radius_top_left = 6
bg_style.corner_radius_top_right = 6
bg_style.corner_radius_bottom_left = 6
bg_style.corner_radius_bottom_right = 6
bg_style.border_width_left = 1
bg_style.border_width_right = 1
bg_style.border_width_top = 1
bg_style.border_width_bottom = 1
bg_style.border_color = _BORDER
bg_style.content_margin_left = 4.0
bg_style.content_margin_right = 4.0
bg_style.content_margin_top = 4.0
bg_style.content_margin_bottom = 4.0
var panel := PanelContainer.new()
panel.custom_minimum_size = Vector2(72.0, 72.0)
panel.add_theme_stylebox_override("panel", bg_style)
vbox.add_child(panel)
var stack := Control.new()
stack.set_anchors_preset(Control.PRESET_FULL_RECT)
panel.add_child(stack)
if ResourceLoader.exists(_ABILITY_ICONS[idx]):
var icon := TextureRect.new()
icon.texture = load(_ABILITY_ICONS[idx])
icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
icon.set_anchors_preset(Control.PRESET_FULL_RECT)
stack.add_child(icon)
var cd_overlay := ColorRect.new()
cd_overlay.color = Color(0.0, 0.0, 0.0, 0.70)
cd_overlay.anchor_left = 0.0
cd_overlay.anchor_right = 1.0
cd_overlay.anchor_top = 1.0
cd_overlay.anchor_bottom = 1.0
cd_overlay.mouse_filter = Control.MOUSE_FILTER_IGNORE
stack.add_child(cd_overlay)
_cd_overlays.append(cd_overlay)
var cd_lbl := Label.new()
cd_lbl.set_anchors_preset(Control.PRESET_FULL_RECT)
cd_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
cd_lbl.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
cd_lbl.mouse_filter = Control.MOUSE_FILTER_IGNORE
cd_lbl.visible = false
cd_lbl.add_theme_color_override("font_color", Color.WHITE)
cd_lbl.add_theme_font_size_override("font_size", 18)
stack.add_child(cd_lbl)
_cd_labels.append(cd_lbl)
var key_lbl := Label.new()
key_lbl.text = Controls.get_key_label(_ABILITY_ACTIONS[idx])
key_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
key_lbl.add_theme_color_override("font_color", _GOLD)
key_lbl.add_theme_font_size_override("font_size", 12)
vbox.add_child(key_lbl)
return vbox
func _build_controls_panel() -> void:
_controls_panel = PanelContainer.new()
var bg := StyleBoxFlat.new()
bg.bg_color = _BG
bg.corner_radius_top_left = 7
bg.corner_radius_top_right = 7
bg.corner_radius_bottom_left = 7
bg.corner_radius_bottom_right = 7
bg.border_width_left = 1
bg.border_width_right = 1
bg.border_width_top = 1
bg.border_width_bottom = 1
bg.border_color = _BORDER
bg.content_margin_left = 14.0
bg.content_margin_right = 14.0
bg.content_margin_top = 10.0
bg.content_margin_bottom = 10.0
_controls_panel.add_theme_stylebox_override("panel", bg)
_controls_panel.anchor_left = 0.0
_controls_panel.anchor_top = 1.0
_controls_panel.anchor_right = 0.0
_controls_panel.anchor_bottom = 1.0
_controls_panel.grow_vertical = Control.GROW_DIRECTION_BEGIN
_controls_panel.offset_left = 20.0
_controls_panel.offset_bottom = -20.0
add_child(_controls_panel)
var vbox := VBoxContainer.new()
vbox.add_theme_constant_override("separation", 5)
_controls_panel.add_child(vbox)
var move_keys := "%s %s %s %s" % [
Controls.get_key_label(&"move_forward"),
Controls.get_key_label(&"move_left"),
Controls.get_key_label(&"move_back"),
Controls.get_key_label(&"move_right"),
]
_row(vbox, move_keys, "Move (not intended)", _MUTED)
_row(vbox, "LMB (hold)", "Right horn", _CREAM)
_row(vbox, "RMB (hold)", "Left horn", _CREAM)
_row(vbox, Controls.get_key_label(&"ability_kick"), "Kick", _CREAM)
_row(vbox, Controls.get_key_label(&"ability_slam"), "Slam", _CREAM)
_row(vbox, Controls.get_key_label(&"ability_dash"), "Dash", _CREAM)
_row(vbox, "Scroll", "Zoom", _CREAM)
_row(vbox, "R", "Respawn matadors (cooldown)", _MUTED)
_row(vbox, "Tab", "Toggle controls", _MUTED)
_row(vbox, "Esc", "Back to menu", _MUTED)
var sep := HSeparator.new()
var sep_style := StyleBoxFlat.new()
sep_style.bg_color = Color(0.65, 0.48, 0.15, 0.30)
sep_style.content_margin_top = 4.0
sep_style.content_margin_bottom = 4.0
sep.add_theme_stylebox_override("separator", sep_style)
vbox.add_child(sep)
var hbox := HBoxContainer.new()
hbox.add_theme_constant_override("separation", 8)
vbox.add_child(hbox)
_toggle_btn = _make_button("Hide controls")
_toggle_btn.pressed.connect(_toggle_controls)
hbox.add_child(_toggle_btn)
var reset_btn := _make_button("Reset")
reset_btn.pressed.connect(_on_reset_pressed)
hbox.add_child(reset_btn)
func _make_button(label_text: String) -> Button:
var btn := Button.new()
btn.text = label_text
btn.process_mode = Node.PROCESS_MODE_ALWAYS
var normal := StyleBoxFlat.new()
normal.bg_color = Color(0.18, 0.12, 0.04, 0.90)
normal.corner_radius_top_left = 5
normal.corner_radius_top_right = 5
normal.corner_radius_bottom_left = 5
normal.corner_radius_bottom_right = 5
normal.border_width_left = 1
normal.border_width_right = 1
normal.border_width_top = 1
normal.border_width_bottom = 1
normal.border_color = _BORDER
normal.content_margin_left = 12.0
normal.content_margin_right = 12.0
normal.content_margin_top = 6.0
normal.content_margin_bottom = 6.0
var hover := StyleBoxFlat.new()
hover.bg_color = Color(0.30, 0.20, 0.06, 0.95)
hover.corner_radius_top_left = 5
hover.corner_radius_top_right = 5
hover.corner_radius_bottom_left = 5
hover.corner_radius_bottom_right = 5
hover.border_width_left = 1
hover.border_width_right = 1
hover.border_width_top = 1
hover.border_width_bottom = 1
hover.border_color = _GOLD
hover.content_margin_left = 12.0
hover.content_margin_right = 12.0
hover.content_margin_top = 6.0
hover.content_margin_bottom = 6.0
btn.add_theme_stylebox_override("normal", normal)
btn.add_theme_stylebox_override("hover", hover)
btn.add_theme_stylebox_override("pressed", hover)
btn.add_theme_color_override("font_color", _GOLD)
btn.add_theme_color_override("font_hover_color", _GOLD)
btn.add_theme_font_size_override("font_size", 12)
return btn
func _row(parent: VBoxContainer, key: String, desc: String, desc_color: Color) -> void:
var row := HBoxContainer.new()
row.add_theme_constant_override("separation", 10)
parent.add_child(row)
var badge := PanelContainer.new()
var bs := StyleBoxFlat.new()
bs.bg_color = _BADGE
bs.corner_radius_top_left = 3
bs.corner_radius_top_right = 3
bs.corner_radius_bottom_left = 3
bs.corner_radius_bottom_right = 3
bs.content_margin_left = 6.0
bs.content_margin_right = 6.0
bs.content_margin_top = 2.0
bs.content_margin_bottom = 2.0
badge.add_theme_stylebox_override("panel", bs)
badge.custom_minimum_size = Vector2(100.0, 0.0)
row.add_child(badge)
var key_lbl := Label.new()
key_lbl.text = key
key_lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
key_lbl.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
key_lbl.add_theme_color_override("font_color", _GOLD)
key_lbl.add_theme_font_size_override("font_size", 12)
badge.add_child(key_lbl)
var desc_lbl := Label.new()
desc_lbl.text = desc
desc_lbl.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
desc_lbl.add_theme_color_override("font_color", desc_color)
desc_lbl.add_theme_font_size_override("font_size", 12)
row.add_child(desc_lbl)