From c391068961642f901cc352d4c8f1fef98f3acbda Mon Sep 17 00:00:00 2001 From: Ruslan Ignatov Date: Sat, 15 Nov 2025 18:33:32 +0300 Subject: [PATCH] Reworked health bar. Added shield regen --- game/entities/ships/abstract_ship.tscn | 11 ++-- .../ships/enemies/abstract_enemy_ship.tscn | 13 ++-- .../enemies/medium/medium_enemy_ship.tscn | 5 +- game/entities/ships/player/player_ship.tscn | 18 +++--- game/health_system/health.gd | 41 ++++++++++-- game/health_system/health.tscn | 10 +++ .../health_bar/health_bar_part.gd | 10 +-- .../health_bar/health_bar_part.tscn | 20 +++--- game/health_system/health_bar/heath_bar.gd | 62 ++++++++++++++----- game/health_system/health_bar/heath_bar.tscn | 41 ++++++++++-- images/health.png | 4 +- 11 files changed, 168 insertions(+), 67 deletions(-) diff --git a/game/entities/ships/abstract_ship.tscn b/game/entities/ships/abstract_ship.tscn index f2c6c78..5d3839b 100644 --- a/game/entities/ships/abstract_ship.tscn +++ b/game/entities/ships/abstract_ship.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=4 format=3 uid="uid://jvyagshykmgb"] +[gd_scene load_steps=5 format=3 uid="uid://jvyagshykmgb"] [ext_resource type="Script" uid="uid://cesibaqtrgotl" path="res://game/entities/ships/abstract_ship.gd" id="1_6isjb"] -[ext_resource type="Script" uid="uid://d3g4xbq45qmpr" path="res://game/health_system/health.gd" id="2_n766o"] +[ext_resource type="PackedScene" uid="uid://clkymhkv3cevm" path="res://game/health_system/health.tscn" id="2_xxtvk"] +[ext_resource type="PackedScene" uid="uid://d2snum2pxc2ui" path="res://game/health_system/health_bar/heath_bar.tscn" id="3_l62e5"] [sub_resource type="CircleShape2D" id="CircleShape2D_xxtvk"] @@ -16,7 +17,7 @@ script = ExtResource("1_6isjb") [node name="CollisionShape2D" type="CollisionShape2D" parent="."] shape = SubResource("CircleShape2D_xxtvk") -[node name="Health" type="Node" parent="."] -script = ExtResource("2_n766o") +[node name="Health" parent="." instance=ExtResource("2_xxtvk")] -[connection signal="depleted" from="Health" to="." method="_on_health_depleted"] +[node name="HeathBar" parent="." node_paths=PackedStringArray("health") instance=ExtResource("3_l62e5")] +health = NodePath("../Health") diff --git a/game/entities/ships/enemies/abstract_enemy_ship.tscn b/game/entities/ships/enemies/abstract_enemy_ship.tscn index aa58ed2..7076e0b 100644 --- a/game/entities/ships/enemies/abstract_enemy_ship.tscn +++ b/game/entities/ships/enemies/abstract_enemy_ship.tscn @@ -1,22 +1,17 @@ -[gd_scene load_steps=5 format=3 uid="uid://dwsn0lf1e3578"] +[gd_scene load_steps=4 format=3 uid="uid://dwsn0lf1e3578"] [ext_resource type="PackedScene" uid="uid://jvyagshykmgb" path="res://game/entities/ships/abstract_ship.tscn" id="1_28j6l"] [ext_resource type="Script" uid="uid://byicf1t0807pq" path="res://game/entities/ships/enemies/abstract_enemy_ship.gd" id="2_fwvrd"] -[ext_resource type="Script" uid="uid://bs8qqj6yepfln" path="res://game/controllers/enemy_controller.gd" id="3_vfnhw"] -[ext_resource type="PackedScene" uid="uid://d2snum2pxc2ui" path="res://game/health_system/health_bar/heath_bar.tscn" id="4_l8c0n"] +[ext_resource type="PackedScene" uid="uid://bsqehbymixust" path="res://game/controllers/enemy_controller.tscn" id="3_l8c0n"] [node name="AbstractEnemyShip" groups=["enemies"] instance=ExtResource("1_28j6l")] collision_layer = 4 collision_mask = 0 script = ExtResource("2_fwvrd") -[node name="EnemyController" type="Node" parent="." index="3"] -script = ExtResource("3_vfnhw") -metadata/_custom_type_script = "uid://bs8qqj6yepfln" - -[node name="HeathBar" parent="." index="4" node_paths=PackedStringArray("health") instance=ExtResource("4_l8c0n")] -health = NodePath("../Health") +[node name="EnemyController" parent="." index="4" instance=ExtResource("3_l8c0n")] +[connection signal="depleted" from="Health" to="." method="_on_health_depleted"] [connection signal="accelerate" from="EnemyController" to="." method="accelerate"] [connection signal="reload" from="EnemyController" to="." method="reload"] [connection signal="shoot" from="EnemyController" to="." method="shoot"] diff --git a/game/entities/ships/enemies/medium/medium_enemy_ship.tscn b/game/entities/ships/enemies/medium/medium_enemy_ship.tscn index f49b701..dc7d9b9 100644 --- a/game/entities/ships/enemies/medium/medium_enemy_ship.tscn +++ b/game/entities/ships/enemies/medium/medium_enemy_ship.tscn @@ -27,4 +27,7 @@ shape = SubResource("CapsuleShape2D_4jmkv") max_hull = 100 [node name="HeathBar" parent="." index="4"] -position = Vector2(0, 30) +offset_top = 30.0 +offset_bottom = 30.0 + +[connection signal="depleted" from="Health" to="." method="_on_health_depleted"] diff --git a/game/entities/ships/player/player_ship.tscn b/game/entities/ships/player/player_ship.tscn index 43761ea..f834e23 100644 --- a/game/entities/ships/player/player_ship.tscn +++ b/game/entities/ships/player/player_ship.tscn @@ -1,9 +1,8 @@ -[gd_scene load_steps=7 format=3 uid="uid://br074cqcnul3d"] +[gd_scene load_steps=6 format=3 uid="uid://br074cqcnul3d"] [ext_resource type="PackedScene" uid="uid://jvyagshykmgb" path="res://game/entities/ships/abstract_ship.tscn" id="1_6otxb"] [ext_resource type="Script" uid="uid://ruxw1n03iq4i" path="res://game/entities/ships/player/player_ship.gd" id="2_625ti"] -[ext_resource type="Script" uid="uid://dgevigih7owxd" path="res://game/controllers/player_controller.gd" id="3_dj8f1"] -[ext_resource type="PackedScene" uid="uid://d2snum2pxc2ui" path="res://game/health_system/health_bar/heath_bar.tscn" id="4_4mjo1"] +[ext_resource type="PackedScene" uid="uid://dh1oj1w5wx4je" path="res://game/controllers/player_controller.tscn" id="3_4mjo1"] [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_dj8f1"] size = Vector2(48, 32) @@ -28,16 +27,17 @@ rotation = 1.5707964 shape = SubResource("CapsuleShape2D_dj8f1") [node name="Health" parent="." index="2"] +max_shield = 1000 +max_armor = 1000 max_hull = 1000 -[node name="PlayerController" type="Node" parent="." index="3"] -script = ExtResource("3_dj8f1") -metadata/_custom_type_script = "uid://dgevigih7owxd" +[node name="HeathBar" parent="." index="3"] +offset_top = 22.0 +offset_bottom = 22.0 -[node name="HeathBar" parent="." index="4" node_paths=PackedStringArray("health") instance=ExtResource("4_4mjo1")] -position = Vector2(0, 22) -health = NodePath("../Health") +[node name="PlayerController" parent="." index="4" instance=ExtResource("3_4mjo1")] +[connection signal="depleted" from="Health" to="." method="_on_health_depleted"] [connection signal="accelerate" from="PlayerController" to="." method="accelerate"] [connection signal="reload" from="PlayerController" to="." method="reload"] [connection signal="shoot" from="PlayerController" to="." method="shoot"] diff --git a/game/health_system/health.gd b/game/health_system/health.gd index 80dba06..84c929f 100644 --- a/game/health_system/health.gd +++ b/game/health_system/health.gd @@ -14,6 +14,10 @@ signal depleted @export_range(1, 5000) var max_hull: int = 1 +@onready var shield_regen_delay_timer : Timer = $ShieldRegenDelayTimer +@onready var shield_regen_tick_timer : Timer = $ShieldRegenTickTimer + + var shield: int: get: return _shield set(value): pass @@ -25,26 +29,51 @@ var hull: int: set(value): pass -@onready var _shield := max_shield -@onready var _armor := max_armor -@onready var _hull := max_hull +@onready var _shield := max_shield: + set(value): + _shield = value + shield_updated.emit(_shield) +@onready var _armor := max_armor: + set(value): + _armor = value + armor_updated.emit(_armor) +@onready var _hull := max_hull: + set(value): + _hull = value + hull_updated.emit(_hull) + +@onready var _shield_regen := floori(max_shield/30.0) func apply_damage(damage: AbstractDamage) -> void: if _shield > 0: var damage_value := ceili(damage.value * damage.shield_damage_multiplier()) _shield = max(_shield - damage_value, 0) - shield_updated.emit(_shield) + shield_regen_delay_timer.start() elif _armor > 0: var damage_value := ceili(damage.value * damage.armor_damage_multiplier()) _armor = max(_armor - damage_value, 0) - armor_updated.emit(_armor) else: if _hull == 0: return var damage_value := ceili(damage.value * damage.hull_damage_multiplier()) _hull = max(_hull - damage_value, 0) - hull_updated.emit(_hull) if _hull == 0: depleted.emit() + + if not shield_regen_delay_timer.is_stopped(): + shield_regen_delay_timer.start() + shield_regen_tick_timer.stop() + + +func _on_shield_regen_delay_timer_timeout() -> void: + shield_regen_tick_timer.start() + + +func _on_shield_regen_tick_timer_timeout() -> void: + var new_shield_value := _shield + _shield_regen + if new_shield_value >= max_shield: + new_shield_value = max_shield + shield_regen_tick_timer.stop() + _shield = new_shield_value diff --git a/game/health_system/health.tscn b/game/health_system/health.tscn index 6b03fd8..5bbbb6c 100644 --- a/game/health_system/health.tscn +++ b/game/health_system/health.tscn @@ -4,3 +4,13 @@ [node name="Health" type="Node"] script = ExtResource("1_gwdg4") + +[node name="ShieldRegenDelayTimer" type="Timer" parent="."] +wait_time = 3.0 +one_shot = true + +[node name="ShieldRegenTickTimer" type="Timer" parent="."] +wait_time = 0.1 + +[connection signal="timeout" from="ShieldRegenDelayTimer" to="." method="_on_shield_regen_delay_timer_timeout"] +[connection signal="timeout" from="ShieldRegenTickTimer" to="." method="_on_shield_regen_tick_timer_timeout"] diff --git a/game/health_system/health_bar/health_bar_part.gd b/game/health_system/health_bar/health_bar_part.gd index d821e6a..9628084 100644 --- a/game/health_system/health_bar/health_bar_part.gd +++ b/game/health_system/health_bar/health_bar_part.gd @@ -1,5 +1,5 @@ class_name HealthBarPart -extends Node2D +extends Control @export var texture_value : Texture2D @export var texture_shade : Texture2D @@ -8,7 +8,7 @@ extends Node2D @onready var value_bar : TextureProgressBar = $ValueBar @onready var shade_bar : TextureProgressBar = $ShadeBar -@onready var shade_reset_timer : Timer = $ShadeResetTimer +@onready var shade_delay_timer : Timer = $ShadeDelayTimer @onready var shade_tick_timer : Timer = $ShadeTickTimer @@ -16,7 +16,7 @@ const TICK_COUNT = 5 var _tick_size : int = 0 -var _target_value: int = 0 +var _target_value: float = 0 func _ready() -> void: @@ -31,7 +31,7 @@ func set_value(value: int) -> void: if shade_bar.value < value_bar.value: shade_bar.value = value_bar.value else: - shade_reset_timer.start() + shade_delay_timer.start() func set_max_value(max_value: int) -> void: @@ -46,7 +46,7 @@ func set_max_value(max_value: int) -> void: shade_bar.show() -func _on_shade_reset_timer_timeout() -> void: +func _on_shade_delay_timer_timeout() -> void: var value_delta := shade_bar.value - value_bar.value _tick_size = ceil(value_delta / TICK_COUNT) _target_value = value_bar.value diff --git a/game/health_system/health_bar/health_bar_part.tscn b/game/health_system/health_bar/health_bar_part.tscn index d68072e..332eadc 100644 --- a/game/health_system/health_bar/health_bar_part.tscn +++ b/game/health_system/health_bar/health_bar_part.tscn @@ -1,16 +1,14 @@ -[gd_scene load_steps=4 format=3 uid="uid://xbfxsiumbgkp"] +[gd_scene load_steps=2 format=3 uid="uid://xbfxsiumbgkp"] [ext_resource type="Script" uid="uid://drwgq8fxaclvn" path="res://game/health_system/health_bar/health_bar_part.gd" id="1_nuv67"] -[ext_resource type="Texture2D" uid="uid://do586oblhwuc5" path="res://images/health.png" id="2_jlvn5"] -[sub_resource type="AtlasTexture" id="AtlasTexture_jlvn5"] -atlas = ExtResource("2_jlvn5") -region = Rect2(0, 48, 32, 16) - -[node name="HealthBarPart" type="Node2D"] +[node name="HealthBarPart" type="Control"] +layout_mode = 3 +anchors_preset = 0 script = ExtResource("1_nuv67") [node name="ShadeBar" type="TextureProgressBar" parent="."] +layout_mode = 1 anchors_preset = 8 anchor_left = 0.5 anchor_top = 0.5 @@ -22,9 +20,10 @@ offset_right = 16.0 offset_bottom = 8.0 grow_horizontal = 2 grow_vertical = 2 -texture_under = SubResource("AtlasTexture_jlvn5") +pivot_offset = Vector2(16, 8) [node name="ValueBar" type="TextureProgressBar" parent="."] +layout_mode = 1 anchors_preset = 8 anchor_left = 0.5 anchor_top = 0.5 @@ -36,13 +35,14 @@ offset_right = 16.0 offset_bottom = 8.0 grow_horizontal = 2 grow_vertical = 2 +pivot_offset = Vector2(16, 8) -[node name="ShadeResetTimer" type="Timer" parent="."] +[node name="ShadeDelayTimer" type="Timer" parent="."] wait_time = 0.5 one_shot = true [node name="ShadeTickTimer" type="Timer" parent="."] wait_time = 0.1 -[connection signal="timeout" from="ShadeResetTimer" to="." method="_on_shade_reset_timer_timeout"] +[connection signal="timeout" from="ShadeDelayTimer" to="." method="_on_shade_delay_timer_timeout"] [connection signal="timeout" from="ShadeTickTimer" to="." method="_on_shade_tick_timer_timeout"] diff --git a/game/health_system/health_bar/heath_bar.gd b/game/health_system/health_bar/heath_bar.gd index 6ee7b4b..6db60ba 100644 --- a/game/health_system/health_bar/heath_bar.gd +++ b/game/health_system/health_bar/heath_bar.gd @@ -1,26 +1,58 @@ class_name HealthBar -extends Node2D +extends Control @export var health: Health -@onready var shield_part : HealthBarPart = $ShieldPart +@onready var small_shield_part : HealthBarPart = $SmallShieldPart +@onready var large_shield_part : HealthBarPart = $LargeShieldPart @onready var armor_part : HealthBarPart = $ArmorPart @onready var hull_part : HealthBarPart = $HullPart func _ready() -> void: - if health: - shield_part.set_max_value(health.max_shield) - shield_part.set_value(health.shield) - - armor_part.set_max_value(health.max_armor) - armor_part.set_value(health.armor) - - hull_part.set_max_value(health.max_hull) - hull_part.set_value(health.hull) - - health.shield_updated.connect(shield_part.set_value) - health.armor_updated.connect(armor_part.set_value) - health.hull_updated.connect(hull_part.set_value) + if not health: return + + small_shield_part.set_max_value(health.max_shield) + small_shield_part.set_value(health.shield) + + large_shield_part.set_max_value(health.max_shield) + large_shield_part.set_value(health.shield) + + armor_part.set_max_value(health.max_armor) + armor_part.set_value(health.armor) + + hull_part.set_max_value(health.max_hull) + hull_part.set_value(health.hull) + + _select_armor_part(health.armor) + + health.shield_updated.connect(_on_shield_updated) + health.armor_updated.connect(_on_armor_updated) + health.hull_updated.connect(_on_hull_updated) + + +func _on_shield_updated(new_value: int) -> void: + small_shield_part.set_value(new_value) + large_shield_part.set_value(new_value) + + +func _on_armor_updated(new_value: int) -> void: + armor_part.set_value(new_value) + _select_armor_part(new_value) + + +func _on_hull_updated(new_value: int) -> void: + hull_part.set_value(new_value) + + +func _select_armor_part(armor_value: int) -> void: + if armor_value == 0: + armor_part.hide() + small_shield_part.show() + large_shield_part.hide() + else: + armor_part.show() + small_shield_part.hide() + large_shield_part.show() diff --git a/game/health_system/health_bar/heath_bar.tscn b/game/health_system/health_bar/heath_bar.tscn index 6b41767..b72266f 100644 --- a/game/health_system/health_bar/heath_bar.tscn +++ b/game/health_system/health_bar/heath_bar.tscn @@ -1,9 +1,13 @@ -[gd_scene load_steps=10 format=3 uid="uid://d2snum2pxc2ui"] +[gd_scene load_steps=13 format=3 uid="uid://d2snum2pxc2ui"] [ext_resource type="Script" uid="uid://be7k64p2kel8b" path="res://game/health_system/health_bar/heath_bar.gd" id="1_bx561"] [ext_resource type="PackedScene" uid="uid://xbfxsiumbgkp" path="res://game/health_system/health_bar/health_bar_part.tscn" id="2_wb6me"] [ext_resource type="Texture2D" uid="uid://do586oblhwuc5" path="res://images/health.png" id="3_fogsl"] +[sub_resource type="AtlasTexture" id="AtlasTexture_sgr4k"] +atlas = ExtResource("3_fogsl") +region = Rect2(0, 64, 32, 16) + [sub_resource type="AtlasTexture" id="AtlasTexture_wb6me"] atlas = ExtResource("3_fogsl") region = Rect2(0, 0, 32, 16) @@ -20,25 +24,52 @@ region = Rect2(0, 16, 32, 16) atlas = ExtResource("3_fogsl") region = Rect2(32, 16, 32, 16) -[sub_resource type="AtlasTexture" id="AtlasTexture_lfh3j"] +[sub_resource type="AtlasTexture" id="AtlasTexture_hknxs"] atlas = ExtResource("3_fogsl") region = Rect2(0, 32, 32, 16) -[sub_resource type="AtlasTexture" id="AtlasTexture_lc4fa"] +[sub_resource type="AtlasTexture" id="AtlasTexture_f0v4d"] atlas = ExtResource("3_fogsl") region = Rect2(32, 32, 32, 16) -[node name="HeathBar" type="Node2D"] +[sub_resource type="AtlasTexture" id="AtlasTexture_lfh3j"] +atlas = ExtResource("3_fogsl") +region = Rect2(0, 48, 32, 16) + +[sub_resource type="AtlasTexture" id="AtlasTexture_lc4fa"] +atlas = ExtResource("3_fogsl") +region = Rect2(32, 48, 32, 16) + +[node name="HeathBar" type="Control"] +layout_mode = 3 +anchors_preset = 0 script = ExtResource("1_bx561") +[node name="Background" type="TextureRect" parent="."] +layout_mode = 0 +offset_left = -16.0 +offset_top = -8.0 +offset_right = 16.0 +offset_bottom = 8.0 +pivot_offset = Vector2(16, 8) +texture = SubResource("AtlasTexture_sgr4k") + [node name="HullPart" parent="." instance=ExtResource("2_wb6me")] +layout_mode = 0 texture_value = SubResource("AtlasTexture_wb6me") texture_shade = SubResource("AtlasTexture_fogsl") [node name="ArmorPart" parent="." instance=ExtResource("2_wb6me")] +layout_mode = 0 texture_value = SubResource("AtlasTexture_b6cw0") texture_shade = SubResource("AtlasTexture_w8ken") -[node name="ShieldPart" parent="." instance=ExtResource("2_wb6me")] +[node name="SmallShieldPart" parent="." instance=ExtResource("2_wb6me")] +layout_mode = 0 +texture_value = SubResource("AtlasTexture_hknxs") +texture_shade = SubResource("AtlasTexture_f0v4d") + +[node name="LargeShieldPart" parent="." instance=ExtResource("2_wb6me")] +layout_mode = 0 texture_value = SubResource("AtlasTexture_lfh3j") texture_shade = SubResource("AtlasTexture_lc4fa") diff --git a/images/health.png b/images/health.png index 8d63d57..52cec74 100644 --- a/images/health.png +++ b/images/health.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4223d6a26db0dd345433e752f685b3d0974cceda015aae853bd3a71e50655c00 -size 231 +oid sha256:20bb14f6b8332e4435f6da5c98bc4d6e956f464e0ae9802863c03c11bb8d23af +size 257