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 <jaro@MacBook.local>
Reviewed-on: #11
pull/12/head^2
Jaro Winkelhausen 2026-04-21 13:16:58 +02:00
parent 9a82e74e41
commit 3f6e76c154
6 changed files with 59 additions and 11 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -1,6 +1,5 @@
extends EnemyBase extends EnemyBase
func _ready() -> void: func _ready() -> void:
super() super()
speed = 15.0 speed = 15.0
@ -8,6 +7,7 @@ func _ready() -> void:
$Area2D.body_entered.connect(_on_area_2d_body_entered) $Area2D.body_entered.connect(_on_area_2d_body_entered)
func _process(delta: float) -> void: func _process(delta: float) -> void:
super._process(delta)
if is_dying or is_hurt: if is_dying or is_hurt:
return return
_chase_witch() _chase_witch()

View File

@ -4,9 +4,12 @@ extends CharacterBody2D
@onready var animated_sprite_2d: AnimatedSprite2D = $AnimatedSprite2D @onready var animated_sprite_2d: AnimatedSprite2D = $AnimatedSprite2D
@export var drop_table: Array[DropTable] @export var drop_table: Array[DropTable]
@export var damage: int = 2
var is_dying = false var is_dying = false
var is_hurt = false var is_hurt = false
var hits_remaining = 1 var hits_remaining = 1
var _touching_witch: bool = false
var speed var speed
var witch var witch
var player var player
@ -21,6 +24,16 @@ func _ready() -> void:
witch = get_node("/root/Game/Witch") witch = get_node("/root/Game/Witch")
player = get_node("/root/Game/Player") player = get_node("/root/Game/Player")
animated_sprite_2d.sprite_frames = animated_sprite_2d.sprite_frames.duplicate() 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(): func die():
is_dying = true is_dying = true
@ -62,9 +75,9 @@ func _play_hurt() -> void:
await animated_sprite_2d.animation_finished await animated_sprite_2d.animation_finished
is_hurt = false is_hurt = false
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void: func _process(delta: float) -> void:
pass if _touching_witch and not is_dying:
witch.take_damage(damage)
func _chase_witch() -> void: func _chase_witch() -> void:
var direction = Vector2(witch.global_position - global_position).normalized() var direction = Vector2(witch.global_position - global_position).normalized()

View File

@ -1,6 +1,5 @@
extends EnemyBase extends EnemyBase
func _ready() -> void: func _ready() -> void:
super() super()
speed = 15.0 speed = 15.0
@ -8,6 +7,7 @@ func _ready() -> void:
$Area2D.body_entered.connect(_on_area_2d_body_entered) $Area2D.body_entered.connect(_on_area_2d_body_entered)
func _process(delta: float) -> void: func _process(delta: float) -> void:
super._process(delta)
if is_dying or is_hurt: if is_dying or is_hurt:
return return
_chase_witch() _chase_witch()

View File

@ -1,22 +1,17 @@
extends EnemyBase 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: func _ready() -> void:
super() super()
speed = 15.0 speed = 15.0
func _process(delta: float) -> void: func _process(delta: float) -> void:
super._process(delta)
if is_dying: if is_dying:
return return
_chase_witch() _chase_witch()
pass
func _on_area_2d_body_entered(body: Node2D) -> void: func _on_area_2d_body_entered(body: Node2D) -> void:
if is_dying: if is_dying:
return return
if body == player: if body == player:
die() die()
pass # Replace with function body.

View File

@ -1,5 +1,7 @@
extends CharacterBody2D extends CharacterBody2D
signal health_changed(current_hp: int, max_hp: int)
var camera var camera
var is_casting = false var is_casting = false
var fireball = preload("res://scenes/fireball.tscn") 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 fire_swirl = preload("res://scenes/fire_swirl.tscn")
var shuriken_count = 1 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: func _ready() -> void:
$CauldronBar.witch = self $CauldronBar.witch = self
camera = get_node("/root/Game/Camera2D") 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: func _physics_process(delta: float) -> void:
# Add the gravity. # Add the gravity.
@ -43,6 +69,20 @@ func shoot_shuriken():
get_parent().add_child(sh) get_parent().add_child(sh)
await get_tree().create_timer(0.2).timeout 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: func get_nearest_enemy(from: Vector2, filter: Callable = Callable()) -> Node:
var nearest = null var nearest = null
var min_distance = INF var min_distance = INF