87 lines
3.6 KiB
GDScript
87 lines
3.6 KiB
GDScript
extends Node2D
|
|
|
|
var player: CharacterBody2D
|
|
var _display_ratio := 1.0
|
|
var _display_shield_ratio := 1.0
|
|
var _display_hull_ratio := 1.0
|
|
var _background: StyleBoxFlat
|
|
|
|
func _ready() -> void:
|
|
# World rendering interpolates this position together with the ship and camera.
|
|
top_level = true
|
|
process_physics_priority = 1
|
|
global_position = player.global_position
|
|
reset_physics_interpolation()
|
|
z_index = 24
|
|
_display_ratio = _energy_ratio()
|
|
_display_shield_ratio = _shield_ratio()
|
|
_display_hull_ratio = _hull_ratio()
|
|
_background = StyleBoxFlat.new()
|
|
_background.bg_color = Color("101925")
|
|
_background.border_color = Color("456277")
|
|
_background.set_border_width_all(1)
|
|
_background.set_corner_radius_all(4)
|
|
_background.shadow_color = Color(0, 0, 0, 0.5)
|
|
_background.shadow_size = 3
|
|
|
|
func _physics_process(_delta: float) -> void:
|
|
if is_instance_valid(player):
|
|
var teleported := global_position.distance_to(player.global_position) > 600.0
|
|
global_position = player.global_position
|
|
if teleported:
|
|
reset_physics_interpolation()
|
|
|
|
func _process(delta: float) -> void:
|
|
if not is_instance_valid(player):
|
|
return
|
|
visible = not bool(player.get("_is_destroyed"))
|
|
var target := _energy_ratio()
|
|
_display_ratio = lerpf(_display_ratio, target, 1.0 - exp(-20.0 * delta))
|
|
if absf(_display_ratio - target) < 0.001:
|
|
_display_ratio = target
|
|
var shield_target := _shield_ratio()
|
|
_display_shield_ratio = lerpf(_display_shield_ratio, shield_target, 1.0 - exp(-20.0 * delta))
|
|
if absf(_display_shield_ratio - shield_target) < 0.001:
|
|
_display_shield_ratio = shield_target
|
|
var hull_target := _hull_ratio()
|
|
_display_hull_ratio = lerpf(_display_hull_ratio, hull_target, 1.0 - exp(-20.0 * delta))
|
|
if absf(_display_hull_ratio - hull_target) < 0.001:
|
|
_display_hull_ratio = hull_target
|
|
queue_redraw()
|
|
|
|
func _energy_ratio() -> float:
|
|
return clampf(float(player.get("energy")) / maxf(1.0, float(player.get("max_energy"))), 0.0, 1.0)
|
|
|
|
func _shield_ratio() -> float:
|
|
return clampf(float(player.get("shields")) / maxf(1.0, float(player.get("max_shields"))), 0.0, 1.0)
|
|
|
|
func _hull_ratio() -> float:
|
|
return clampf(float(player.get("hull")) / maxf(1.0, float(player.get("max_hull"))), 0.0, 1.0)
|
|
|
|
func _draw() -> void:
|
|
if not is_instance_valid(player):
|
|
return
|
|
_draw_bar(Vector2(-46, 58), _display_ratio, Color("efbd62"), 0)
|
|
_draw_bar(Vector2(-46, 72), _display_shield_ratio, Color("66cfff"), 1)
|
|
_draw_bar(Vector2(-46, 86), _display_hull_ratio, Color("ef6875"), 2)
|
|
|
|
func _draw_bar(position: Vector2, ratio: float, color: Color, kind: int) -> void:
|
|
draw_style_box(_background, Rect2(position - Vector2(14, 3), Vector2(110, 12)))
|
|
# Ten illuminated cells, with partial cells tracking the exact current value.
|
|
for index in 10:
|
|
var cell := Rect2(position + Vector2(index * 9.2, 0), Vector2(7.6, 6))
|
|
draw_rect(cell, color.darkened(0.8))
|
|
var fraction := clampf(ratio * 10.0 - index, 0.0, 1.0)
|
|
if fraction > 0:
|
|
cell.size.x *= fraction
|
|
draw_rect(cell, color)
|
|
draw_rect(Rect2(cell.position, Vector2(cell.size.x, 2)), color.lightened(0.4))
|
|
var center := position + Vector2(-8, 3)
|
|
match kind:
|
|
0:
|
|
draw_polyline(PackedVector2Array([center + Vector2(1, -4), center + Vector2(-2, 0), center + Vector2(2, 0), center + Vector2(-1, 4)]), color, 1.4, true)
|
|
1:
|
|
draw_polyline(PackedVector2Array([center + Vector2(-3, -3), center + Vector2(3, -3), center + Vector2(2, 2), center + Vector2(0, 4), center + Vector2(-2, 2), center + Vector2(-3, -3)]), color, 1.2, true)
|
|
2:
|
|
draw_polyline(PackedVector2Array([center + Vector2(0, -4), center + Vector2(3, 0), center + Vector2(2, 3), center + Vector2(-2, 3), center + Vector2(-3, 0), center + Vector2(0, -4)]), color, 1.2, true)
|