From 547b22b2c0151f719daf2231bacb886f30eca4ee Mon Sep 17 00:00:00 2001 From: Nathan Chapman Date: Sun, 18 May 2025 17:52:58 -0600 Subject: [PATCH] Add health bar --- project.godot | 7 ++ src/resources/characters/character_stats.gd | 2 + src/scenes/characters/player.tscn | 75 +++++++------- src/scenes/ui/inventory.tscn | 9 ++ src/scenes/ui/user_interface.tscn | 102 ++++++++++++++++++++ src/scripts/characters/health_component.gd | 3 + src/scripts/characters/player.gd | 3 + src/scripts/ui/user_interface.gd | 18 ++++ src/scripts/ui/user_interface.gd.uid | 1 + 9 files changed, 185 insertions(+), 35 deletions(-) create mode 100644 src/scenes/ui/inventory.tscn create mode 100644 src/scenes/ui/user_interface.tscn create mode 100644 src/scripts/ui/user_interface.gd create mode 100644 src/scripts/ui/user_interface.gd.uid diff --git a/project.godot b/project.godot index b064d50..c35166d 100644 --- a/project.godot +++ b/project.godot @@ -19,6 +19,13 @@ config/icon="res://icon.svg" VFXManager="*res://src/scenes/autoload/vfx_manager.tscn" +[display] + +window/size/viewport_width=1920 +window/size/viewport_height=1080 +window/size/mode=3 +window/stretch/mode="canvas_items" + [editor_plugins] enabled=PackedStringArray("res://addons/sky_3d/plugin.cfg", "res://addons/terrain_3d/plugin.cfg") diff --git a/src/resources/characters/character_stats.gd b/src/resources/characters/character_stats.gd index 6bef478..ebbb1c5 100644 --- a/src/resources/characters/character_stats.gd +++ b/src/resources/characters/character_stats.gd @@ -1,6 +1,7 @@ class_name CharacterStats extends Resource signal level_up_notification() +signal update_stats() class Ability: var min_modifier: float @@ -32,6 +33,7 @@ var xp: int = 0: xp -= boundary level_up() boundary = perc_level_up_boundary() + update_stats.emit() const MIN_DASH_COOLDOWN: float = 1.5 const MAX_DASH_COOLDOWN: float = 0.5 diff --git a/src/scenes/characters/player.tscn b/src/scenes/characters/player.tscn index 28314f9..cff0c02 100644 --- a/src/scenes/characters/player.tscn +++ b/src/scenes/characters/player.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=12 format=3 uid="uid://nsv4lbw7j8mi"] +[gd_scene load_steps=13 format=3 uid="uid://nsv4lbw7j8mi"] [ext_resource type="Script" uid="uid://csgybabwb8cbg" path="res://src/scripts/characters/player.gd" id="1_swhsd"] [ext_resource type="PackedScene" uid="uid://dw8f5oy13cdtx" path="res://src/scenes/characters/health_component.tscn" id="2_0xash"] @@ -8,6 +8,7 @@ [ext_resource type="Script" uid="uid://blbnvx6pe37mc" path="res://src/scripts/characters/attack_cast.gd" id="4_cx3ie"] [ext_resource type="PackedScene" uid="uid://bo62qyfwylypa" path="res://src/scenes/characters/area_attack.tscn" id="6_wmokw"] [ext_resource type="PackedScene" uid="uid://cwdsfw1g1607y" path="res://src/scenes/characters/dash.tscn" id="7_yvk1n"] +[ext_resource type="PackedScene" uid="uid://blex30jj7g55d" path="res://src/scenes/ui/user_interface.tscn" id="9_wdvff"] [sub_resource type="Resource" id="Resource_wdvff"] script = ExtResource("2_ulq46") @@ -47,53 +48,53 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0) [node name="Rig" parent="RigPivot" instance=ExtResource("3_n52bt")] [node name="Skeleton3D" parent="RigPivot/Rig/CharacterRig/GameRig" index="0"] -bones/0/position = Vector3(4.44089e-15, 0.908602, -0.0481736) +bones/0/position = Vector3(9.10632e-15, 0.897796, -0.0481735) bones/0/rotation = Quaternion(0.12582, 1.18262e-07, 1.49989e-08, 0.992053) bones/1/rotation = Quaternion(-0.0566577, -0.00072973, -0.0117082, 0.998325) bones/2/position = Vector3(3.20474e-09, 0.146689, -1.95578e-08) -bones/2/rotation = Quaternion(0.00557797, -0.000295829, 0.00321172, 0.999979) +bones/2/rotation = Quaternion(-0.00137182, -0.000408462, 0.00321463, 0.999994) bones/3/position = Vector3(-2.01263e-09, 0.202058, -2.51457e-08) -bones/3/rotation = Quaternion(-0.0897188, -0.000291992, 0.00852419, 0.995931) +bones/3/rotation = Quaternion(-0.0960596, -0.000374465, 0.00852031, 0.995339) bones/4/position = Vector3(3.02934e-10, 0.0925562, 3.91155e-08) -bones/4/rotation = Quaternion(0.270961, 1.46734e-08, 9.11671e-08, 0.96259) +bones/4/rotation = Quaternion(0.276725, 1.55382e-08, 9.05906e-08, 0.960949) bones/5/rotation = Quaternion(-0.0948564, -2.80691e-14, -2.26155e-08, 0.995491) -bones/6/rotation = Quaternion(-0.16386, -1.17681e-07, -1.90351e-08, 0.986484) -bones/7/position = Vector3(-2.52885e-08, 0.908602, -0.0481735) +bones/6/rotation = Quaternion(-0.156608, -1.1777e-07, -1.84686e-08, 0.987661) +bones/7/position = Vector3(-1.64274e-08, 0.897796, -0.0481734) bones/7/rotation = Quaternion(-0.0863677, -0.751104, -0.383052, 0.530711) -bones/8/position = Vector3(-7.81021e-08, 0.908602, -0.0481735) +bones/8/position = Vector3(-7.15453e-08, 0.897796, -0.0481735) bones/8/rotation = Quaternion(-0.0863677, 0.751104, 0.383052, 0.530711) -bones/9/position = Vector3(0.131144, 0.974806, -0.0351291) -bones/9/rotation = Quaternion(0.994101, 0.0203247, -0.031211, 0.101863) +bones/9/position = Vector3(0.131144, 0.964001, -0.0351291) +bones/9/rotation = Quaternion(0.993043, 0.020862, -0.0309536, 0.111679) bones/10/position = Vector3(-2.36129e-08, 0.26601, -2.14789e-08) bones/10/rotation = Quaternion(-3.13921e-08, -0.000695086, 1.20449e-08, 1) bones/11/position = Vector3(-4.6306e-08, 0.26601, 2.42145e-08) -bones/11/rotation = Quaternion(0.398241, -0.000696108, 0.000302346, 0.917281) +bones/11/rotation = Quaternion(0.420385, -0.000700496, 0.000324692, 0.907346) bones/12/position = Vector3(3.05151e-08, 0.22603, 5.03768e-08) bones/12/rotation = Quaternion(-8.19226e-09, -0.00710644, 4.16102e-08, 0.999975) bones/13/position = Vector3(-2.95495e-08, 0.22603, 2.68392e-09) -bones/13/rotation = Quaternion(-0.742137, 0.0118505, 0.0243655, 0.6697) +bones/13/rotation = Quaternion(-0.751659, 0.0118859, 0.0244045, 0.658993) bones/14/position = Vector3(-3.05481e-08, 0.139877, 1.64787e-08) bones/14/rotation = Quaternion(-9.66743e-05, 0.967474, -0.252972, -0.000383447) -bones/15/position = Vector3(-0.131144, 0.974806, -0.0351291) -bones/15/rotation = Quaternion(0.97549, -0.00534217, 0.0276274, 0.218238) +bones/15/position = Vector3(-0.131144, 0.964001, -0.0351291) +bones/15/rotation = Quaternion(0.973202, -0.00578121, 0.0273228, 0.228249) bones/16/position = Vector3(-1.10042e-08, 0.265705, -3.31989e-08) bones/16/rotation = Quaternion(-3.43227e-08, 0.00314323, 8.33075e-10, 0.999995) bones/17/position = Vector3(1.83545e-08, 0.265705, 6.98543e-10) -bones/17/rotation = Quaternion(0.424128, 0.00317259, -0.00148598, 0.905596) +bones/17/rotation = Quaternion(0.444398, 0.00329248, -0.00163343, 0.895822) bones/18/position = Vector3(1.2807e-08, 0.225719, -8.28774e-09) bones/18/rotation = Quaternion(-2.29017e-08, -0.00785732, 3.30149e-08, 0.999969) bones/19/position = Vector3(-1.27748e-08, 0.225719, 1.12004e-08) -bones/19/rotation = Quaternion(-0.679419, -0.0281455, -0.00135688, 0.73321) +bones/19/rotation = Quaternion(-0.68825, -0.028193, -0.000730449, 0.724925) bones/20/position = Vector3(-1.30142e-08, 0.139877, -2.77457e-09) bones/20/rotation = Quaternion(-9.96472e-05, 0.967461, -0.253021, -0.000383039) -bones/21/position = Vector3(0.0251286, 1.43822, 0.0465997) -bones/21/rotation = Quaternion(-0.473296, -0.266141, -0.414697, 0.730196) -bones/22/position = Vector3(0.191109, 1.47689, -0.0116832) -bones/22/rotation = Quaternion(0.0248291, -0.163488, 0.9754, -0.145772) +bones/21/position = Vector3(0.0251286, 1.42797, 0.0426986) +bones/21/rotation = Quaternion(-0.491549, -0.258729, -0.401319, 0.728273) +bones/22/position = Vector3(0.188732, 1.46498, -0.0229053) +bones/22/rotation = Quaternion(0.0479058, -0.159993, 0.97454, -0.1496) bones/23/position = Vector3(-5.41331e-09, 0.143946, -2.98023e-08) -bones/23/rotation = Quaternion(3.5172e-08, -0.0362841, 3.9968e-08, 0.999342) +bones/23/rotation = Quaternion(5.96391e-08, -0.0175512, 7.66073e-08, 0.999846) bones/24/position = Vector3(-6.33301e-08, 0.143946, 4.3873e-08) -bones/24/rotation = Quaternion(0.345166, -0.0362848, -0.0215455, 0.937592) +bones/24/rotation = Quaternion(0.302664, -0.0175519, -0.0185676, 0.952755) bones/25/position = Vector3(1.30385e-08, 0.127601, 6.51926e-09) bones/25/rotation = Quaternion(1.49943e-07, -1.20606e-07, 9.91859e-08, 1) bones/26/position = Vector3(2.06034e-08, 0.127601, 2.42761e-08) @@ -118,14 +119,14 @@ bones/42/rotation = Quaternion(-0.120913, 0.799109, 0.0358921, 0.587807) bones/43/rotation = Quaternion(0.498693, -0.0202705, -0.0256953, 0.866161) bones/44/rotation = Quaternion(0.715385, 0.035306, 0.0573145, 0.695481) bones/45/rotation = Quaternion(-0.129059, 0.728936, -0.0250259, 0.67184) -bones/46/position = Vector3(-0.0113635, 1.43822, 0.0465997) -bones/46/rotation = Quaternion(-0.476105, 0.258893, 0.410235, 0.733489) -bones/47/position = Vector3(-0.176177, 1.47719, -0.0147045) -bones/47/rotation = Quaternion(-0.0191112, -0.146327, 0.975926, 0.160597) +bones/46/position = Vector3(-0.0113635, 1.42797, 0.0426986) +bones/46/rotation = Quaternion(-0.509052, 0.222962, 0.376924, 0.741001) +bones/47/position = Vector3(-0.16781, 1.46546, -0.0382827) +bones/47/rotation = Quaternion(-0.0717007, -0.137456, 0.973476, 0.168253) bones/48/position = Vector3(1.88476e-07, 0.143946, 1.02445e-08) -bones/48/rotation = Quaternion(1.18242e-07, 0.0515202, 1.4879e-07, 0.998672) +bones/48/rotation = Quaternion(1.02745e-07, 0.0159803, 1.16495e-07, 0.999872) bones/49/position = Vector3(6.5191e-09, 0.143946, -1.95094e-08) -bones/49/rotation = Quaternion(0.38489, 0.0515208, 0.0282148, 0.921091) +bones/49/rotation = Quaternion(0.336074, 0.0159807, 0.0289808, 0.941254) bones/50/position = Vector3(-1.48779e-07, 0.1276, 5.9139e-08) bones/50/rotation = Quaternion(-8.73115e-08, 2.7474e-08, -1.28057e-07, 1) bones/51/position = Vector3(1.9461e-07, 0.127601, 6.06248e-08) @@ -151,19 +152,19 @@ bones/67/rotation = Quaternion(0.108364, -0.768224, 0.166291, 0.608635) bones/68/rotation = Quaternion(0.629954, 0.0295149, 0.0177509, 0.775869) bones/69/rotation = Quaternion(0.816678, -0.0439534, -0.0509861, 0.573155) bones/70/rotation = Quaternion(-0.12906, -0.728937, 0.0250258, 0.67184) -bones/71/position = Vector3(0.127191, 1.3589, -0.0246982) -bones/71/rotation = Quaternion(2.01819e-08, 0.60028, 0.79979, -4.59287e-08) -bones/72/position = Vector3(-0.113426, 1.3589, -0.0246982) -bones/72/rotation = Quaternion(2.0182e-08, 0.60028, 0.79979, -4.59287e-08) +bones/71/position = Vector3(0.127191, 1.34658, -0.0262327) +bones/71/rotation = Quaternion(1.93793e-08, 0.612015, 0.790846, -4.63801e-08) +bones/72/position = Vector3(-0.113426, 1.34658, -0.0262327) +bones/72/rotation = Quaternion(1.93794e-08, 0.612015, 0.790846, -4.63801e-08) [node name="RightHandBone" parent="RigPivot/Rig" index="2"] -transform = Transform3D(-0.962343, -0.270801, -0.0237148, 0.224021, -0.839459, 0.4951, -0.153981, 0.471143, 0.868512, -0.349993, 1.00858, 0.0223412) +transform = Transform3D(-0.962343, -0.270804, -0.0237128, 0.23972, -0.886535, 0.395715, -0.128183, 0.375129, 0.918067, -0.341627, 0.984705, -0.0250425) [node name="LeftHandBone" parent="RigPivot/Rig" index="3"] -transform = Transform3D(-0.970513, 0.239108, 0.0305213, -0.210586, -0.902654, 0.375325, 0.117293, 0.357831, 0.92639, 0.347919, 0.991902, -0.0125405) +transform = Transform3D(-0.970514, 0.239108, 0.0305212, -0.220736, -0.932453, 0.286019, 0.096849, 0.270848, 0.957738, 0.345543, 0.972205, -0.045435) [node name="RayAttachment" type="BoneAttachment3D" parent="RigPivot/Rig"] -transform = Transform3D(-0.962343, -0.270801, -0.0237148, 0.224021, -0.839459, 0.4951, -0.153981, 0.471143, 0.868512, -0.349993, 1.00858, 0.0223412) +transform = Transform3D(-0.962343, -0.270804, -0.0237128, 0.23972, -0.886535, 0.395715, -0.128183, 0.375129, 0.918067, -0.341627, 0.984705, -0.0250425) bone_name = "DEF-hand.R" bone_idx = 51 use_external_skeleton = true @@ -184,7 +185,11 @@ collision_mask = 8 transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.191783, 0) player = NodePath("../..") +[node name="UserInterface" parent="." node_paths=PackedStringArray("player") instance=ExtResource("9_wdvff")] +player = NodePath("..") + [connection signal="defeat" from="HealthComponent" to="." method="_on_health_component_defeat"] +[connection signal="health_changed" from="HealthComponent" to="UserInterface" method="update_health"] [connection signal="heavy_attack" from="RigPivot/Rig" to="." method="_on_rig_heavy_attack"] [editable path="RigPivot/Rig"] diff --git a/src/scenes/ui/inventory.tscn b/src/scenes/ui/inventory.tscn new file mode 100644 index 0000000..cd7b787 --- /dev/null +++ b/src/scenes/ui/inventory.tscn @@ -0,0 +1,9 @@ +[gd_scene format=3 uid="uid://csadps2at3npv"] + +[node name="Inventory" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 diff --git a/src/scenes/ui/user_interface.tscn b/src/scenes/ui/user_interface.tscn new file mode 100644 index 0000000..38cd044 --- /dev/null +++ b/src/scenes/ui/user_interface.tscn @@ -0,0 +1,102 @@ +[gd_scene load_steps=8 format=3 uid="uid://blex30jj7g55d"] + +[ext_resource type="Texture2D" uid="uid://b7gexelwfg2wp" path="res://assets/ui/unitframe/health_bar_under.png" id="1_qhv2u"] +[ext_resource type="Script" uid="uid://5d05pjburasd" path="res://src/scripts/ui/user_interface.gd" id="1_xba4v"] +[ext_resource type="Texture2D" uid="uid://cqm2xl55pcii8" path="res://assets/ui/unitframe/health_bar_over.png" id="2_nxqqf"] +[ext_resource type="Texture2D" uid="uid://bvwedh6c8rvg" path="res://assets/ui/unitframe/main_bar.png" id="3_j2uiq"] +[ext_resource type="FontFile" uid="uid://xseb06nenn48" path="res://assets/fonts/Candara.ttf" id="3_nxqqf"] +[ext_resource type="Texture2D" uid="uid://dn2npqh8ue3vy" path="res://assets/ui/unitframe/blue_bar.png" id="4_ma5hf"] + +[sub_resource type="LabelSettings" id="LabelSettings_xba4v"] +font = ExtResource("3_nxqqf") +font_size = 26 +font_color = Color(0.960784, 0.717647, 0.423529, 1) + +[node name="UserInterface" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +script = ExtResource("1_xba4v") + +[node name="MarginContainer" type="MarginContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +theme_override_constants/margin_left = 32 +theme_override_constants/margin_top = 32 +theme_override_constants/margin_right = 32 +theme_override_constants/margin_bottom = 32 + +[node name="InfoBar" type="Control" parent="MarginContainer"] +layout_mode = 2 +mouse_filter = 2 + +[node name="HealthBarUnder" type="TextureRect" parent="MarginContainer/InfoBar"] +layout_mode = 0 +offset_right = 40.0 +offset_bottom = 40.0 +texture = ExtResource("1_qhv2u") + +[node name="HealthBar" type="TextureProgressBar" parent="MarginContainer/InfoBar/HealthBarUnder"] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +value = 100.0 +texture_progress = ExtResource("3_j2uiq") + +[node name="HealthLabel" type="Label" parent="MarginContainer/InfoBar/HealthBarUnder/HealthBar"] +unique_name_in_owner = true +custom_minimum_size = Vector2(96, 0) +layout_mode = 1 +anchors_preset = 9 +anchor_bottom = 1.0 +offset_left = 94.0 +offset_top = -13.0 +offset_right = 194.0 +offset_bottom = -20.0 +grow_vertical = 2 +text = "999" +label_settings = SubResource("LabelSettings_xba4v") +vertical_alignment = 1 + +[node name="XPBar" type="TextureProgressBar" parent="MarginContainer/InfoBar/HealthBarUnder"] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture_progress = ExtResource("4_ma5hf") + +[node name="HealthBarOver" type="TextureRect" parent="MarginContainer/InfoBar"] +layout_mode = 0 +offset_right = 40.0 +offset_bottom = 40.0 +texture = ExtResource("2_nxqqf") + +[node name="LevelLabel" type="Label" parent="MarginContainer/InfoBar/HealthBarOver"] +unique_name_in_owner = true +custom_minimum_size = Vector2(96, 0) +layout_mode = 1 +anchors_preset = 9 +anchor_bottom = 1.0 +offset_right = 96.0 +offset_bottom = -7.0 +grow_vertical = 2 +text = "999" +label_settings = SubResource("LabelSettings_xba4v") +horizontal_alignment = 1 +vertical_alignment = 1 diff --git a/src/scripts/characters/health_component.gd b/src/scripts/characters/health_component.gd index ee6122b..34ecbe8 100644 --- a/src/scripts/characters/health_component.gd +++ b/src/scripts/characters/health_component.gd @@ -24,3 +24,6 @@ func take_damage(damage_in: float, is_critical: bool) -> void: damage *= 2.0 current_health -= damage VFXManager.spawn_damage_number(damage, body.global_position, is_critical) + +func get_health_string() -> String: + return "%s/%s" % [current_health, max_health] diff --git a/src/scripts/characters/player.gd b/src/scripts/characters/player.gd index d5c0715..cd1fd36 100644 --- a/src/scripts/characters/player.gd +++ b/src/scripts/characters/player.gd @@ -24,6 +24,7 @@ var _attack_direction: Vector3 = Vector3.ZERO @onready var health_component: HealthComponent = $HealthComponent @onready var collision_shape: CollisionShape3D = $CollisionShape @onready var area_attack: ShapeCast3D = $RigPivot/AreaAttack +@onready var ui: Control = $UserInterface func _ready() -> void: Input.mouse_mode = Input.MOUSE_MODE_CAPTURED @@ -31,6 +32,8 @@ func _ready() -> void: stats.level_up_notification.connect( func(): health_component.update_max_health(stats.get_max_hp()) ) + stats.update_stats.connect(ui.update_stats_display) + ui.update_stats_display() func _physics_process(delta: float) -> void: frame_camera_rotation() diff --git a/src/scripts/ui/user_interface.gd b/src/scripts/ui/user_interface.gd new file mode 100644 index 0000000..78b51ad --- /dev/null +++ b/src/scripts/ui/user_interface.gd @@ -0,0 +1,18 @@ +extends Control + +@onready var level_label: Label = %LevelLabel +@onready var health_bar: TextureProgressBar = %HealthBar +@onready var xp_bar: TextureProgressBar = %XPBar +@onready var health_label: Label = %HealthLabel + +@export var player: Player + +func update_stats_display() -> void: + level_label.text = str(player.stats.level) + xp_bar.max_value = player.stats.perc_level_up_boundary() + xp_bar.value = player.stats.xp + +func update_health() -> void: + health_bar.max_value = player.health_component.max_health + health_bar.value = player.health_component.current_health + health_label.text = player.health_component.get_health_string() diff --git a/src/scripts/ui/user_interface.gd.uid b/src/scripts/ui/user_interface.gd.uid new file mode 100644 index 0000000..057e196 --- /dev/null +++ b/src/scripts/ui/user_interface.gd.uid @@ -0,0 +1 @@ +uid://5d05pjburasd