aboutsummaryrefslogtreecommitdiff
path: root/src/player.odin
diff options
context:
space:
mode:
Diffstat (limited to 'src/player.odin')
-rw-r--r--src/player.odin130
1 files changed, 122 insertions, 8 deletions
diff --git a/src/player.odin b/src/player.odin
index 2f82e2f..7a0ee45 100644
--- a/src/player.odin
+++ b/src/player.odin
@@ -10,6 +10,8 @@ import "fw"
Player_State :: enum {
Default,
Dash,
+ Wall_Slide,
+ Wall_Jump,
}
// there will only ever be one player, so just make it a global :)
@@ -25,6 +27,8 @@ player: struct {
coyote_time: f32,
dash_cooldown: f32,
dash_timer: f32,
+ wall_jump_timer: f32,
+ wall_slide_dir: f32,
state: Player_State,
outside_room: bool,
has_double_jumped: bool,
@@ -82,6 +86,28 @@ _get_input_dir :: proc() -> f32 {
}
@(private = "file")
+_can_wallslide :: proc(input: f32) -> bool {
+ pos := phys.get_position(player.body)
+ rect := phys.get_rect(player.body)
+ rect.start += pos
+
+ top_start := rect.start + {rect.size.x * 0.5, 0}
+ top_end := top_start + {input * 8, 0}
+
+ bot_start := rect.start + {rect.size.x * 0.5, rect.size.y}
+ bot_end := bot_start + {input * 8, 0}
+
+ top_rc := phys.make_raycast(top_start, top_end)
+ bot_rc := phys.make_raycast(bot_start, bot_end)
+
+ top_touching := phys.is_colliding(top_rc)
+ bot_touching := phys.is_colliding(bot_rc)
+
+ vel := phys.get_velocity(player.body)
+ return vel.y > 0 && top_touching && bot_touching
+}
+
+@(private = "file")
_default_state :: proc(dt: f32) {
input := _get_input_dir()
@@ -119,6 +145,10 @@ _default_state :: proc(dt: f32) {
case:
set_sprite_active_tag(&player.sprite, "jump_trans")
}
+
+ if _can_wallslide(input) {
+ _enter_wall_slide()
+ }
}
rel_mouse_pos := fw.get_mouse_pos() - pos
@@ -214,6 +244,69 @@ _exit_dash :: proc() {
}
@(private = "file")
+_enter_wall_slide :: proc() {
+ player.has_double_jumped = false
+ player.wall_slide_dir = _get_input_dir()
+ player.state = .Wall_Slide
+}
+
+@(private = "file")
+_wall_slide_state :: proc(dt: f32) {
+ set_sprite_active_tag(&player.sprite, "idle")
+
+ input := _get_input_dir()
+
+ collisions := phys.get_collisions(player.body)
+
+ if !_can_wallslide(player.wall_slide_dir) {
+ player.state = .Default
+ }
+
+ vel := phys.get_velocity(player.body)
+
+ vel.x = dt_lerp(
+ vel.x,
+ input * PLAYER_SPEED,
+ PLAYER_ACCEL,
+ )
+ vel.y = PLAYER_WALL_SLIDE_SPEED
+
+ phys.set_velocity(player.body, vel)
+
+ phys.update_body(player.body)
+
+ if fw.is_keybind_just_down(actions.jump) {
+ _enter_wall_jump()
+ }
+}
+
+@(private = "file")
+_enter_wall_jump :: proc() {
+ vel := phys.get_velocity(player.body)
+ vel.x = -player.wall_slide_dir * PLAYER_WALL_JUMP_FORCE
+ vel.y = -PLAYER_JUMP_FORCE
+ phys.set_velocity(player.body, vel)
+
+ player.state = .Wall_Jump
+
+ player.wall_jump_timer = PLAYER_WALL_JUMP_TIME
+}
+
+@(private = "file")
+_wall_jump_state :: proc(dt: f32) {
+ phys.update_body(player.body)
+
+ player.wall_jump_timer -= dt
+ if player.wall_jump_timer <= 0 {
+ vel := phys.get_velocity(player.body)
+ vel.y = PLAYER_JUMP_RELEASE_CUT * 2
+ phys.set_velocity(player.body, vel)
+
+ player.state = .Default
+ }
+}
+
+@(private = "file")
_get_camera_target_pos :: proc() -> Vec2 {
pos := phys.get_position(player.body) - SCREEN_SIZE * 0.5
room_size := Vec2{
@@ -268,6 +361,8 @@ update_player :: proc(dt: f32) {
switch player.state {
case .Default: _default_state(dt)
case .Dash: _dash_state(dt)
+ case .Wall_Slide: _wall_slide_state(dt)
+ case .Wall_Jump: _wall_jump_state(dt)
}
pos := phys.get_position(player.body)
@@ -313,16 +408,35 @@ draw_player :: proc() {
draw_player_fg :: proc() {
rc_start := phys.get_position(player.body)
dir := Vec2{math.cos(player.gun.sprite.rotation), math.sin(player.gun.sprite.rotation)}
- bodies := phys.get_colliding_bodies(phys.make_raycast(rc_start, dir), allocator = context.temp_allocator)
- is_colliding := len(bodies) > 0
-
- color := fw.GREEN if is_colliding else fw.RED
- fw.draw_line(rc_start, rc_start + dir * 500, color = color)
+ rc_end := rc_start + dir * 32
+ collision, is_colliding := phys.get_closest_raycast_collision(
+ phys.make_raycast(rc_start, rc_end),
+ )
- for body in bodies {
- rect := phys.get_rect(body)
- fw.draw_rect(rect.start, rect.size, color = fw.RED)
+ if is_colliding {
+ rect := phys.get_rect(collision.body)
+ fw.draw_rect(rect.start, rect.size, color = Color{0, 1, 1, 0.5})
+ fw.draw_line(rc_start, rc_end, color = fw.GREEN)
+ fw.draw_rect(collision.enter, {1, 1}, color = fw.RED)
+ fw.draw_rect(collision.exit, {1, 1}, color = fw.BLUE)
}
+
+ input := _get_input_dir()
+ pos := phys.get_position(player.body)
+ rect := phys.get_rect(player.body)
+ rect.start += pos
+
+ top_start := rect.start + {rect.size.x * 0.5, 0}
+ top_end := top_start + {input * 8, 0}
+
+ bot_start := rect.start + {rect.size.x * 0.5, rect.size.y}
+ bot_end := bot_start + {input * 8, 0}
+
+ fw.draw_line(top_start, top_end)
+ fw.draw_line(bot_start, bot_end)
+
+ // top_rc := phys.make_raycast(top_start, top_end)
+ // bot_rc := phys.make_raycast(bot_start, bot_end)
}
@(private = "file")