From 3f6e76c1542e39dcad1ceb6f698f14137192ca24 Mon Sep 17 00:00:00 2001 From: Jaro Winkelhausen <3002102@stud.hs-mannheim.de> Date: Tue, 21 Apr 2026 13:16:58 +0200 Subject: [PATCH] added an actual hp/damage system to the witch and enemies game over screen is still missing the game just restarts (#11) Co-authored-by: Jaro Reviewed-on: https://gitty.informatik.hs-mannheim.de/3002102/gae_wild_jam/pulls/11 --- .DS_Store | Bin 10244 -> 10244 bytes scripts/blue_slime.gd | 2 +- scripts/enemy_base.gd | 17 +++++++++++++++-- scripts/fire_slime.gd | 2 +- scripts/slime.gd | 9 ++------- scripts/witch.gd | 40 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 59 insertions(+), 11 deletions(-) diff --git a/.DS_Store b/.DS_Store index e6636b058d6127c1098fe7d5671c3d10eff14758..41d0a7cb12c89407b4b85d157df2c3d4c00c8f15 100644 GIT binary patch delta 32 ocmZn(XbG6$&&aniU^hP_-)0^G8_vyVB(2#dHnePJSNO{g0I*gH(EtDd delta 136 zcmZn(XbG6$&nU1lU^hRbz-Ar+8_sZkhGd3BhEj$ch7^V(hJ1!RhIob~phyve9z!}q zif2xKa#Buy5(5K+00RRP6Oh*X4+cOM1A{Ow-IHadWcZkhkd<$Cm9%5q%&zd49RM`3 BB=`UT diff --git a/scripts/blue_slime.gd b/scripts/blue_slime.gd index ad489b0..1bb95e3 100644 --- a/scripts/blue_slime.gd +++ b/scripts/blue_slime.gd @@ -1,6 +1,5 @@ extends EnemyBase - func _ready() -> void: super() speed = 15.0 @@ -8,6 +7,7 @@ func _ready() -> void: $Area2D.body_entered.connect(_on_area_2d_body_entered) func _process(delta: float) -> void: + super._process(delta) if is_dying or is_hurt: return _chase_witch() diff --git a/scripts/enemy_base.gd b/scripts/enemy_base.gd index 85133a9..3ccd2b9 100644 --- a/scripts/enemy_base.gd +++ b/scripts/enemy_base.gd @@ -4,9 +4,12 @@ extends CharacterBody2D @onready var animated_sprite_2d: AnimatedSprite2D = $AnimatedSprite2D @export var drop_table: Array[DropTable] +@export var damage: int = 2 + var is_dying = false var is_hurt = false var hits_remaining = 1 +var _touching_witch: bool = false var speed var witch var player @@ -21,6 +24,16 @@ func _ready() -> void: witch = get_node("/root/Game/Witch") player = get_node("/root/Game/Player") animated_sprite_2d.sprite_frames = animated_sprite_2d.sprite_frames.duplicate() + $Area2D.body_entered.connect(_on_base_body_entered) + $Area2D.body_exited.connect(_on_base_body_exited) + +func _on_base_body_entered(body: Node2D) -> void: + if body == witch: + _touching_witch = true + +func _on_base_body_exited(body: Node2D) -> void: + if body == witch: + _touching_witch = false func die(): is_dying = true @@ -62,9 +75,9 @@ func _play_hurt() -> void: await animated_sprite_2d.animation_finished is_hurt = false -# Called every frame. 'delta' is the elapsed time since the previous frame. func _process(delta: float) -> void: - pass + if _touching_witch and not is_dying: + witch.take_damage(damage) func _chase_witch() -> void: var direction = Vector2(witch.global_position - global_position).normalized() diff --git a/scripts/fire_slime.gd b/scripts/fire_slime.gd index 8e3ca5b..39a3ca9 100644 --- a/scripts/fire_slime.gd +++ b/scripts/fire_slime.gd @@ -1,6 +1,5 @@ extends EnemyBase - func _ready() -> void: super() speed = 15.0 @@ -8,6 +7,7 @@ func _ready() -> void: $Area2D.body_entered.connect(_on_area_2d_body_entered) func _process(delta: float) -> void: + super._process(delta) if is_dying or is_hurt: return _chase_witch() diff --git a/scripts/slime.gd b/scripts/slime.gd index a928d3e..785b7cc 100644 --- a/scripts/slime.gd +++ b/scripts/slime.gd @@ -1,22 +1,17 @@ extends EnemyBase - -# Called when the node enters the scene tree for the first time. - -# Called every frame. 'delta' is the elapsed time since the previous frame.+ func _ready() -> void: super() - speed = 15.0 + speed = 15.0 func _process(delta: float) -> void: + super._process(delta) if is_dying: return _chase_witch() - pass func _on_area_2d_body_entered(body: Node2D) -> void: if is_dying: return if body == player: die() - pass # Replace with function body. diff --git a/scripts/witch.gd b/scripts/witch.gd index f792f42..17aaa37 100644 --- a/scripts/witch.gd +++ b/scripts/witch.gd @@ -1,5 +1,7 @@ extends CharacterBody2D +signal health_changed(current_hp: int, max_hp: int) + var camera var is_casting = false var fireball = preload("res://scenes/fireball.tscn") @@ -7,9 +9,33 @@ var shuriken = preload("res://scenes/shuriken.tscn") var fire_swirl = preload("res://scenes/fire_swirl.tscn") var shuriken_count = 1 +var max_hp: int = 100 +var current_hp: int = 100 +var is_invincible: bool = false + +const HP_BAR_WIDTH = 20 +const HP_BAR_HEIGHT = 3 +var _hp_bar_fill: ColorRect + func _ready() -> void: $CauldronBar.witch = self camera = get_node("/root/Game/Camera2D") + _setup_hp_bar() + +func _setup_hp_bar() -> void: + var bg = ColorRect.new() + bg.color = Color(0.15, 0.15, 0.15, 0.85) + bg.size = Vector2(HP_BAR_WIDTH, HP_BAR_HEIGHT) + bg.position = Vector2(-HP_BAR_WIDTH / 2.0, 18) + add_child(bg) + _hp_bar_fill = ColorRect.new() + _hp_bar_fill.color = Color(0.85, 0.1, 0.1, 1.0) + _hp_bar_fill.size = Vector2(HP_BAR_WIDTH, HP_BAR_HEIGHT) + _hp_bar_fill.position = Vector2(-HP_BAR_WIDTH / 2.0, 18) + add_child(_hp_bar_fill) + +func _update_hp_bar() -> void: + _hp_bar_fill.size.x = HP_BAR_WIDTH * (float(current_hp) / float(max_hp)) func _physics_process(delta: float) -> void: # Add the gravity. @@ -43,6 +69,20 @@ func shoot_shuriken(): get_parent().add_child(sh) await get_tree().create_timer(0.2).timeout +func take_damage(amount: int) -> void: + if is_invincible: + return + current_hp -= amount + current_hp = max(current_hp, 0) + health_changed.emit(current_hp, max_hp) + _update_hp_bar() + if current_hp <= 0: + get_tree().call_deferred("reload_current_scene") + return + is_invincible = true + await get_tree().create_timer(1.0).timeout + is_invincible = false + func get_nearest_enemy(from: Vector2, filter: Callable = Callable()) -> Node: var nearest = null var min_distance = INF