From 5b417b540b73c0a2411521a3e7bdb3a81fa7b757 Mon Sep 17 00:00:00 2001 From: Michael Campbell Date: Wed, 4 Mar 2026 17:17:57 -0500 Subject: [PATCH] stamina and health bar --- icon.svg.import | 13 ++-- player/health_bar.gd | 16 ++++ player/health_bar.gd.uid | 1 + player/hp_outline.gdshader | 13 ++++ player/hp_outline.gdshader.uid | 1 + player/player.gd | 9 ++- player/player.tscn | 130 ++++++++++++++++++++++++++++++++- player/stamina_bar.gd | 10 +++ player/stamina_bar.gd.uid | 1 + 9 files changed, 184 insertions(+), 10 deletions(-) create mode 100644 player/health_bar.gd create mode 100644 player/health_bar.gd.uid create mode 100644 player/hp_outline.gdshader create mode 100644 player/hp_outline.gdshader.uid create mode 100644 player/stamina_bar.gd create mode 100644 player/stamina_bar.gd.uid diff --git a/icon.svg.import b/icon.svg.import index 14c5053..0a144e1 100644 --- a/icon.svg.import +++ b/icon.svg.import @@ -3,19 +3,20 @@ importer="texture" type="CompressedTexture2D" uid="uid://dvlbutpkwnj27" -path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +path.s3tc="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.s3tc.ctex" metadata={ -"vram_texture": false +"imported_formats": ["s3tc_bptc"], +"vram_texture": true } [deps] source_file="res://icon.svg" -dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.s3tc.ctex"] [params] -compress/mode=0 +compress/mode=2 compress/high_quality=false compress/lossy_quality=0.7 compress/uastc_level=0 @@ -23,7 +24,7 @@ compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 -mipmaps/generate=false +mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" @@ -37,7 +38,7 @@ process/normal_map_invert_y=false process/hdr_as_srgb=false process/hdr_clamp_exposure=false process/size_limit=0 -detect_3d/compress_to=1 +detect_3d/compress_to=0 svg/scale=1.0 editor/scale_with_editor_scale=false editor/convert_colors_with_editor_theme=false diff --git a/player/health_bar.gd b/player/health_bar.gd new file mode 100644 index 0000000..3e3a105 --- /dev/null +++ b/player/health_bar.gd @@ -0,0 +1,16 @@ +extends Control + +func _ready() -> void: + get_parent().modulate.a = 0. + +func update(value: int) -> void: + if value == 3: return + get_parent().modulate.a = 1. + + for child in get_children(): + child.visible = value > 0 + value -= 1 + + create_tween() \ + .tween_property(get_parent(), "modulate:a", 0., 1.) \ + .set_delay(2.) diff --git a/player/health_bar.gd.uid b/player/health_bar.gd.uid new file mode 100644 index 0000000..d355c0e --- /dev/null +++ b/player/health_bar.gd.uid @@ -0,0 +1 @@ +uid://urxp3pg8g2mh diff --git a/player/hp_outline.gdshader b/player/hp_outline.gdshader new file mode 100644 index 0000000..8609744 --- /dev/null +++ b/player/hp_outline.gdshader @@ -0,0 +1,13 @@ +shader_type canvas_item; + +void fragment() { + float dist_from_edge_x = .5 - abs(UV.x - .5); + float dist_from_edge_y = .5 - abs(UV.y - .5); + + // dist_from_edge in pixels + float dfe_xpx = dist_from_edge_x * 100.; + float dfe_ypx = dist_from_edge_y * 40.; + float dfe_px = min(dfe_xpx, dfe_ypx); + + COLOR.a *= dfe_px < 7.5 ? 1. : 0.; +} diff --git a/player/hp_outline.gdshader.uid b/player/hp_outline.gdshader.uid new file mode 100644 index 0000000..e21f3b3 --- /dev/null +++ b/player/hp_outline.gdshader.uid @@ -0,0 +1 @@ +uid://cf3h3knluytmm diff --git a/player/player.gd b/player/player.gd index 58113bc..8e6b669 100644 --- a/player/player.gd +++ b/player/player.gd @@ -11,6 +11,7 @@ enum State { const MOVE_SPEED := 7.5 const DASH_SPEED := 25. +const DASH_COST := .5 static var instance: Player @@ -25,6 +26,7 @@ var health := 3: health = v if is_node_ready(): %HealthLabel.text = "Health: %d" % v + %HealthBar.update(v) var state := State.NORMAL var dash_direction: Vector2 @@ -59,8 +61,8 @@ func _process_movement(delta: float) -> void: velocity = exp_lerp(velocity, desired_velocity, 20, delta) move_and_slide() - if Input.is_action_just_pressed("dash") and stamina >= 1. and not input.is_zero_approx(): - stamina = 0. + if Input.is_action_just_pressed("dash") and stamina >= DASH_COST and not input.is_zero_approx(): + stamina -= DASH_COST dash_direction = input state = State.DASHING await get_tree().create_timer(.25, false).timeout @@ -139,6 +141,7 @@ func _process(delta: float) -> void: gun_index += 1 func damage(damager: Node3D) -> void: + if health <= 0: return if state == State.DASHING: damager.queue_free() else: @@ -147,5 +150,5 @@ func damage(damager: Node3D) -> void: damage_clock = 3 shake_duration = .25 - if health == 0: + if health <= 0: died.emit() diff --git a/player/player.tscn b/player/player.tscn index cab79ba..5afa143 100644 --- a/player/player.tscn +++ b/player/player.tscn @@ -6,6 +6,9 @@ [ext_resource type="Script" uid="uid://fv1n5noqdfg2" path="res://player/guns/basic_gun.gd" id="3_g1dw6"] [ext_resource type="Script" uid="uid://b87cyvu2m5b1k" path="res://player/guns/mini_gun.gd" id="4_yw30f"] [ext_resource type="Script" uid="uid://ftrngxkkycl1" path="res://player/guns/mortar.gd" id="5_qjkh3"] +[ext_resource type="Script" uid="uid://urxp3pg8g2mh" path="res://player/health_bar.gd" id="7_boad6"] +[ext_resource type="Shader" uid="uid://cf3h3knluytmm" path="res://player/hp_outline.gdshader" id="8_rgyib"] +[ext_resource type="Script" uid="uid://ban0rphntn10r" path="res://player/stamina_bar.gd" id="9_hg6s5"] [sub_resource type="FastNoiseLite" id="FastNoiseLite_onrkg"] @@ -18,6 +21,18 @@ size = Vector3(2, 0.1, 0.1) [sub_resource type="SphereMesh" id="SphereMesh_4flbx"] +[sub_resource type="ViewportTexture" id="ViewportTexture_g6k8r"] +viewport_path = NodePath("OnPlayerHUD") + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_hg6s5"] +shader = ExtResource("8_rgyib") + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_rgyib"] +bg_color = Color(0.23, 0.23, 0.23, 0.34901962) + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_hg6s5"] +bg_color = Color(0.30492008, 0.84, 0.18480001, 1) + [node name="Player" type="CharacterBody3D" unique_id=1904432250 node_paths=PackedStringArray("guns")] collision_layer = 2 collision_mask = 13 @@ -61,6 +76,7 @@ script = ExtResource("2_onrkg") [node name="HealthLabel" type="Label" parent="PlayerHUD" unique_id=1653322479] unique_name_in_owner = true +visible = false anchors_preset = 10 anchor_right = 1.0 offset_bottom = 67.0 @@ -71,7 +87,7 @@ text = "Health: 2" horizontal_alignment = 2 [node name="StaminaBar" type="ProgressBar" parent="PlayerHUD" unique_id=961689130] -unique_name_in_owner = true +visible = false anchors_preset = 7 anchor_left = 0.5 anchor_top = 1.0 @@ -121,3 +137,115 @@ fire_rate = 800.0 unique_name_in_owner = true script = ExtResource("5_qjkh3") fire_rate = 160.0 + +[node name="OnPlayerHUDSprite" type="Sprite3D" parent="." unique_id=1611457281] +transform = Transform3D(2.5426614, 0, 0, 0, 1.4438343, 2.0929568, 0, -2.0929568, 1.4438343, 0, 3.1055684, 0.17435753) +texture = SubResource("ViewportTexture_g6k8r") + +[node name="OnPlayerHUD" type="SubViewport" parent="." unique_id=477940783] +transparent_bg = true +size = Vector2i(512, 200) + +[node name="Modulator" type="Control" parent="OnPlayerHUD" unique_id=1763321617] +layout_mode = 3 +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="HealthBar" type="Control" parent="OnPlayerHUD/Modulator" unique_id=1594760840] +unique_name_in_owner = true +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 +script = ExtResource("7_boad6") + +[node name="HLeft" type="ColorRect" parent="OnPlayerHUD/Modulator/HealthBar" unique_id=868789341] +layout_mode = 1 +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = 76.0 +offset_right = 176.0 +offset_bottom = 40.0 +grow_horizontal = 2 +color = Color(1, 0, 0, 1) + +[node name="HMiddle" type="ColorRect" parent="OnPlayerHUD/Modulator/HealthBar" unique_id=1539420729] +layout_mode = 1 +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = 186.0 +offset_right = 286.0 +offset_bottom = 40.0 +grow_horizontal = 2 +color = Color(1, 0, 0, 1) + +[node name="HRight" type="ColorRect" parent="OnPlayerHUD/Modulator/HealthBar" unique_id=1676746583] +layout_mode = 1 +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = 296.0 +offset_right = 396.0 +offset_bottom = 40.0 +grow_horizontal = 2 +color = Color(1, 0, 0, 1) + +[node name="HealthbarOutline" type="Control" parent="OnPlayerHUD/Modulator" unique_id=1389427565] +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 + +[node name="HLeft" type="ColorRect" parent="OnPlayerHUD/Modulator/HealthbarOutline" unique_id=1163991791] +material = SubResource("ShaderMaterial_hg6s5") +layout_mode = 1 +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = 76.0 +offset_right = 176.0 +offset_bottom = 40.0 +grow_horizontal = 2 +color = Color(1, 0.31, 0.31, 1) + +[node name="HMiddle" type="ColorRect" parent="OnPlayerHUD/Modulator/HealthbarOutline" unique_id=1489109783] +material = SubResource("ShaderMaterial_hg6s5") +layout_mode = 1 +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = 186.0 +offset_right = 286.0 +offset_bottom = 40.0 +grow_horizontal = 2 +color = Color(1, 0.31, 0.31, 1) + +[node name="HRight" type="ColorRect" parent="OnPlayerHUD/Modulator/HealthbarOutline" unique_id=1936619089] +material = SubResource("ShaderMaterial_hg6s5") +layout_mode = 1 +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = 296.0 +offset_right = 396.0 +offset_bottom = 40.0 +grow_horizontal = 2 +color = Color(1, 0.31, 0.31, 1) + +[node name="StaminaBar" type="ProgressBar" parent="OnPlayerHUD" unique_id=1360991619] +unique_name_in_owner = true +anchors_preset = 5 +anchor_left = 0.5 +anchor_right = 0.5 +offset_left = -160.0 +offset_top = 50.0 +offset_right = 160.0 +offset_bottom = 77.0 +grow_horizontal = 2 +theme_override_styles/background = SubResource("StyleBoxFlat_rgyib") +theme_override_styles/fill = SubResource("StyleBoxFlat_hg6s5") +max_value = 1.0 +value = 1.0 +show_percentage = false +script = ExtResource("9_hg6s5") diff --git a/player/stamina_bar.gd b/player/stamina_bar.gd new file mode 100644 index 0000000..ca865bb --- /dev/null +++ b/player/stamina_bar.gd @@ -0,0 +1,10 @@ +extends ProgressBar + +var clock := 2. +func _process(delta: float) -> void: + modulate.a = clampf(remap(clock, .5, 1., 1., 0.), 0., 1.) + + if value == max_value: + clock += delta + else: + clock = 0 diff --git a/player/stamina_bar.gd.uid b/player/stamina_bar.gd.uid new file mode 100644 index 0000000..9ed5587 --- /dev/null +++ b/player/stamina_bar.gd.uid @@ -0,0 +1 @@ +uid://ban0rphntn10r