aboutsummaryrefslogtreecommitdiff
path: root/src/player.odin
diff options
context:
space:
mode:
authoriamcheeseman <[email protected]>2026-03-03 21:13:32 -0500
committeriamcheeseman <[email protected]>2026-03-03 21:13:32 -0500
commit86f95e0737ba082625c22d40057e66499cbc8ac1 (patch)
treec86336bf0a21b7740d8b5416424b30c4bb3eee9e /src/player.odin
parent11d72700ad9afd1d23bdae730edf5b160e99fde4 (diff)
Health and dying
Diffstat (limited to 'src/player.odin')
-rw-r--r--src/player.odin73
1 files changed, 64 insertions, 9 deletions
diff --git a/src/player.odin b/src/player.odin
index 4747e65..592552d 100644
--- a/src/player.odin
+++ b/src/player.odin
@@ -12,17 +12,15 @@ Player_State :: enum {
Dash,
Wall_Slide,
Wall_Jump,
+ Dead,
}
// there will only ever be one player, so just make it a global :)
player: struct {
- body: phys.Body_Handle,
- sprite: Sprite,
- gun: struct {
- sprite: Sprite,
- kickback: f32,
- },
- scarf: Tail(7),
+ health: i16,
+ max_health: i16,
+
+ hit_timestamp: f32,
jump_buffer: f32,
coyote_time: f32,
dash_cooldown: f32,
@@ -33,6 +31,14 @@ player: struct {
outside_room: bool,
has_double_jumped: bool,
fall_height: f32,
+ body: phys.Body_Handle,
+
+ sprite: Sprite,
+ scarf: Tail(7),
+ gun: struct {
+ sprite: Sprite,
+ kickback: f32,
+ },
owns_double_jump: bool,
owns_dash: bool,
@@ -44,6 +50,7 @@ init_player :: proc() {
layers = {.Player},
mask = {.Hard}
)
+
player.body = body
init_sprite(&player.sprite, .Player)
@@ -62,6 +69,9 @@ init_player :: proc() {
color_start = Color {0.18, 0.13, 0.18, 1} * 0.5,
color_end = {0.18, 0.13, 0.18, 1},
}
+
+ player.max_health = 10
+ player.health = 10
}
deinit_player :: proc() {
@@ -211,8 +221,12 @@ _default_state :: proc(dt: f32) {
if .Down in new_collisions && .Down not_in collisions {
// just landed
height := phys.get_position(player.body).y
- if height - player.fall_height > 16 * 16 {
- log.info("DEAD")
+
+ distance_fallen := height - player.fall_height
+ if distance_fallen > MAX_SAFE_FALL_HEIGHT {
+ distance_fallen -= MAX_SAFE_FALL_HEIGHT
+ damage := (distance_fallen / MAX_FALL_HEIGHT) * PLAYER_MAX_FALL_DAMAGE
+ player_take_damage(damage, {0, 0})
}
}
@@ -383,6 +397,7 @@ update_player :: proc(dt: f32) {
case .Dash: _dash_state(dt)
case .Wall_Slide: _wall_slide_state(dt)
case .Wall_Jump: _wall_jump_state(dt)
+ case .Dead:
}
pos := phys.get_position(player.body)
@@ -423,6 +438,46 @@ draw_player :: proc() {
if player.state != .Dash {
draw_sprite(player.gun.sprite)
}
+
+ health_bar_size := Vec2{16, 2}
+
+ pos := player.sprite.pos
+ pos.x -= health_bar_size.x / 2
+ pos.y -= 24
+
+ fw.draw_rect(
+ pos - {1, 1},
+ health_bar_size + {2, 2},
+ color = fw.WHITE,
+ )
+
+ fw.draw_progress_bar(
+ pos,
+ health_bar_size,
+ fw.RED,
+ fw.BLACK,
+ f32(player.health) / f32(player.max_health),
+ )
+}
+
+player_take_damage :: proc(#any_int amt: i16, kb_dir: Vec2) {
+ current_time := f32(fw.get_time())
+
+ if current_time - player.hit_timestamp < 0.2 {
+ return
+ }
+
+ player.hit_timestamp = current_time
+
+ player.health -= amt
+ player.health = math.clamp(player.health, 0, player.max_health)
+
+ if player.health == 0 {
+ player.state = .Dead
+ }
+
+ vel := phys.get_velocity(player.body) + kb_dir
+ phys.set_velocity(player.body, vel)
}
draw_player_fg :: proc() {