diff options
| author | Xander Swan <[hidden email]> | 2026-01-01 18:32:20 -0500 |
|---|---|---|
| committer | Xander Swan <[hidden email]> | 2026-01-01 18:32:20 -0500 |
| commit | 65a2ceda55198dab3bab75c06c0d50adeb0a1101 (patch) | |
| tree | 2a08400520f60fcd86b381bc840bb5c739ff998a /src/player.odin | |
| parent | dc373b507ca68ada2cbf4c8e0d7949d6bc46ed9b (diff) | |
lots of changes + player dash
Diffstat (limited to 'src/player.odin')
| -rw-r--r-- | src/player.odin | 180 |
1 files changed, 142 insertions, 38 deletions
diff --git a/src/player.odin b/src/player.odin index 5d7ffb4..5c001da 100644 --- a/src/player.odin +++ b/src/player.odin @@ -7,25 +7,42 @@ import rl "vendor:raylib" import "draw" import "phys" +import "tiled" PLAYER_SPEED :: 100 PLAYER_ACCEL :: 10 PLAYER_JUMP_FORCE :: 350 -JUMP_BUFFERING :: 0.07 -COYOTE_TIME :: 0.05 -JUMP_RELEASE_CUT :: -100 +PLAYER_JUMP_BUFFERING :: 0.07 +PLAYER_COYOTE_TIME :: 0.05 +PLAYER_JUMP_RELEASE_CUT :: -100 -Player :: struct { +PLAYER_DASH_SPEED :: 500 +PLAYER_DASH_TIME :: 0.15 +PLAYER_DASH_COOLDOWN :: 0.3 + +Player_State :: enum { + DEFAULT, + DASH, +} + +// there will only ever be one player, so just make it a global :) +player: struct { body_handle: phys.Body_Handle, anim: draw.Animation, sprite: draw.Sprite, jump_buffer: f32, coyote_time: f32, + + dash_cooldown: f32, + dash_timer: f32, + + state: Player_State, + outside_room: bool, } -init_player :: proc(p: ^Player) { - anim_ok := draw.init_anim_data(&p.anim, "res/player.json") +init_player :: proc() { + anim_ok := draw.init_anim_data(&player.anim, "res/player.json") if !anim_ok { log.warn("could not load animation") rl.CloseWindow() @@ -33,28 +50,29 @@ init_player :: proc(p: ^Player) { } handle, body := phys.make_body( - phys.Rect{{8, 17}, {16, 16}}, + phys.Rect{{-4, 17}, {8, 16}}, ) - p.body_handle = handle + player.body_handle = handle phys.set_body_position(handle, Vec2{50, 100}) - draw.init_sprite(&p.sprite, p.anim.image_path, p.anim) + draw.init_sprite(&player.sprite, player.anim.image_path, player.anim) - p.sprite.offset = Vec2{ - -math.floor(f32(p.sprite.width / 2)), - -f32(p.sprite.height) + player.sprite.offset = Vec2{ + math.floor(f32(player.sprite.width / 2)), + -f32(player.sprite.height) } } -delete_player :: proc(p: Player) { - phys.remove_body(p.body_handle) +delete_player :: proc() { + phys.remove_body(player.body_handle) - draw.destroy_sprite(p.sprite) - draw.delete_anim_data(p.anim) + draw.destroy_sprite(player.sprite) + draw.delete_anim_data(player.anim) } -update_player :: proc(p: ^Player, dt: f32) { +@(private="file") +get_input_dir :: proc() -> f32 { input: f32 if is_keybind_down(actions.move_left) { @@ -64,33 +82,45 @@ update_player :: proc(p: ^Player, dt: f32) { input += 1 } - if is_keybind_just_down(actions.jump) { - p.jump_buffer = JUMP_BUFFERING - } + return input +} + +@(private="file") +default_state :: proc(dt: f32) { + input := get_input_dir() if input != 0 { - draw.set_sprite_active_tag(&p.sprite, "run") - p.sprite.scale.x = math.sign(input) + draw.set_sprite_active_tag(&player.sprite, "run") + player.sprite.scale.x = math.sign(input) } else { - draw.set_sprite_active_tag(&p.sprite, "idle") + draw.set_sprite_active_tag(&player.sprite, "idle") + } + + if is_keybind_just_down(actions.jump) { + player.jump_buffer = PLAYER_JUMP_BUFFERING + } + + if is_keybind_just_down(actions.dash) && player.dash_cooldown <= 0 { + enter_dash() + return } - body := phys.get_body(p.body_handle) - + body := phys.get_body(player.body_handle) + if .DOWN in body.collisions { - p.coyote_time = COYOTE_TIME + player.coyote_time = PLAYER_COYOTE_TIME } - if p.jump_buffer > 0 && p.coyote_time > 0 { - p.jump_buffer = 0 - p.coyote_time = 0 + if player.jump_buffer > 0 && player.coyote_time > 0 { + player.jump_buffer = 0 + player.coyote_time = 0 body.vel.y = -PLAYER_JUMP_FORCE } if .DOWN not_in body.collisions \ && !is_keybind_down(actions.jump) \ - && body.vel.y < JUMP_RELEASE_CUT { - body.vel.y = JUMP_RELEASE_CUT + && body.vel.y < PLAYER_JUMP_RELEASE_CUT { + body.vel.y = PLAYER_JUMP_RELEASE_CUT } body.vel.x = math.lerp( @@ -100,16 +130,90 @@ update_player :: proc(p: ^Player, dt: f32) { ) body.vel.y = math.min(body.vel.y + GRAVITY * dt, TERMINAL_VELOCITY) - phys.update_body(p.body_handle) + phys.update_body(player.body_handle) +} + +@(private="file") +enter_dash :: proc() { + body := phys.get_body(player.body_handle) + // the sprite x scale is the direction the player is facing :) + body.vel = {math.sign(player.sprite.scale.x) * PLAYER_DASH_SPEED, 0} + + player.dash_timer = PLAYER_DASH_TIME + player.state = .DASH +} + +@(private="file") +dash_state :: proc(dt: f32) { + phys.update_body(player.body_handle) + + player.dash_timer -= dt + body := phys.get_body(player.body_handle) + + if player.dash_timer <= 0 || body.collisions != {} { + exit_dash() + } +} + +exit_dash :: proc() { + player.state = .DEFAULT + + player.dash_cooldown = PLAYER_DASH_COOLDOWN + + body := phys.get_body(player.body_handle) + body.vel /= 2 +} + +@(private="file") +change_rooms :: proc() { + body := phys.get_body(player.body_handle) - p.sprite.pos = body.pos - draw.update_sprite(&p.sprite, dt) + width := f32(tiled.current_room.room.width) + height := f32(tiled.current_room.room.height) - p.jump_buffer -= dt - p.coyote_time -= dt + if body.pos.x < 0 || body.pos.x > width \ + || body.pos.y < 0 || body.pos.y > height { + prev_room_pos := [2]f32{ + f32(tiled.current_room.room.x), + f32(tiled.current_room.room.y), + } + changed := tiled.open_new_room_at({i32(body.pos.x), i32(body.pos.y)}) + + if changed { + new_room_pos := [2]f32{ + f32(tiled.current_room.room.x), + f32(tiled.current_room.room.y), + } + + diff := prev_room_pos - new_room_pos + new_pos := body.pos + diff - {0, 0} + phys.set_body_position(player.body_handle, new_pos) + + setup_map_collisions() + } + } } -draw_player :: proc(p: Player) { - draw.sprite(p.sprite) +update_player :: proc(dt: f32) { + switch player.state { + case .DEFAULT: + default_state(dt) + case .DASH: + dash_state(dt) + } + + body := phys.get_body(player.body_handle) + + player.sprite.pos = body.pos + draw.update_sprite(&player.sprite, dt) + + player.dash_cooldown -= dt + player.jump_buffer -= dt + player.coyote_time -= dt + + change_rooms() } +draw_player :: proc() { + draw.sprite(player.sprite) +} |
