package demonchime import "core:log" import "core:math" import rl "vendor:raylib" import "draw" import "phys" PLAYER_SPEED :: 100 PLAYER_ACCEL :: 10 PLAYER_JUMP_FORCE :: 350 JUMP_BUFFERING :: 0.07 COYOTE_TIME :: 0.05 JUMP_RELEASE_CUT :: -100 Player :: struct { body_handle: phys.Body_Handle, anim: draw.Animation, sprite: draw.Sprite, jump_buffer: f32, coyote_time: f32, } init_player :: proc(p: ^Player) { anim_ok := draw.init_anim_data(&p.anim, "res/player.json") if !anim_ok { log.warn("could not load animation") rl.CloseWindow() return } handle, body := phys.make_body( phys.Rect{{8, 17}, {16, 16}}, ) p.body_handle = handle body.pos = Vec2{50, 0} draw.init_sprite(&p.sprite, p.anim.image_path, p.anim) p.sprite.offset = Vec2{ -math.floor(f32(p.sprite.width / 2)), -f32(p.sprite.height) } } delete_player :: proc(p: Player) { phys.remove_body(p.body_handle) draw.destroy_sprite(p.sprite) draw.delete_anim_data(p.anim) } update_player :: proc(p: ^Player, dt: f32) { input: f32 if is_keybind_down(actions.move_left) { input -= 1 } if is_keybind_down(actions.move_right) { input += 1 } if is_keybind_just_down(actions.jump) { p.jump_buffer = JUMP_BUFFERING } if input != 0 { draw.set_sprite_active_tag(&p.sprite, "run") p.sprite.scale.x = math.sign(input) } else { draw.set_sprite_active_tag(&p.sprite, "idle") } body := phys.get_body(p.body_handle) if .DOWN in body.collisions { p.coyote_time = COYOTE_TIME } if p.jump_buffer > 0 && p.coyote_time > 0 { p.jump_buffer = 0 p.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.x = math.lerp( body.vel.x, input * PLAYER_SPEED, math.pow(0.5, dt * PLAYER_ACCEL), ) body.vel.y = math.min(body.vel.y + GRAVITY * dt, TERMINAL_VELOCITY) phys.update_body(p.body_handle) p.sprite.pos = body.pos draw.update_sprite(&p.sprite, dt) p.jump_buffer -= dt p.coyote_time -= dt } draw_player :: proc(p: Player) { draw.sprite(p.sprite) }