package game import "core:fmt" import rl "vendor:raylib" Player_State :: enum { IDLE, WALK, ATTACK } Player :: struct { position: rl.Vector2, velocity: rl.Vector2, speed: f32, // max move speed accel: f32, // how fast to reach speed friction: f32, // how fast to stop state: Player_State, animation: AnimationState, flipped: bool, collider_offset: rl.Vector2, collider_w: f32, collider_h: f32 } player_init :: proc(assets: ^Player_Assets) -> Player { player := Player{} player.position = {39, 39} player.speed = 180 player.accel = 720 player.friction = 640 player.state = .IDLE player.collider_offset = rl.Vector2{8, 15} player.collider_w = 16 player.collider_h = 10 animation_play(&player.animation, &assets.clips[.IDLE]) return player } get_player_center :: proc(player: ^Player) -> rl.Vector2 { return rl.Vector2{ player.position.x + TILE_SIZE / 2, player.position.y + TILE_SIZE / 2, } } get_player_collider :: proc(player: ^Player, pos: rl.Vector2) -> rl.Rectangle { return rl.Rectangle{ (pos.x + player.collider_offset.x), pos.y + player.collider_offset.y, player.collider_w, player.collider_h, } } update_player :: proc(player: ^Player, assets: ^Player_Assets, camera: rl.Camera2D, game_map: Game_Map) { moving := false dt := rl.GetFrameTime() input_dir := rl.Vector2{0,0} if rl.IsKeyDown(.W) { moving = true; input_dir.y -=1; } if rl.IsKeyDown(.S) { moving = true; input_dir.y +=1; } if rl.IsKeyDown(.A) { moving = true; input_dir.x -=1; player.flipped = true } if rl.IsKeyDown(.D) { moving = true; input_dir.x +=1; player.flipped = false } has_input := input_dir.x != 0 || input_dir.y != 0 if has_input { input_dir = rl.Vector2Normalize(input_dir) } // Move velocity toward target (accelerate) or toward zero (friction) target_velocity := input_dir * player.speed if has_input { player.velocity = rl.Vector2MoveTowards(player.velocity, target_velocity, player.accel * dt) } else { player.velocity = rl.Vector2MoveTowards(player.velocity, rl.Vector2{0, 0}, player.friction * dt) } // Check for collisions new_position := player.velocity * dt new_x_pos := rl.Vector2{player.position.x + new_position.x, player.position.y} if !check_map_collision(get_player_collider(player, new_x_pos), game_map) { player.position.x = new_x_pos.x } else { player.velocity.x = 0 } new_y_pos := rl.Vector2{player.position.x, player.position.y + new_position.y} if !check_map_collision(get_player_collider(player, new_y_pos), game_map) { player.position.y = new_y_pos.y } else { player.velocity.y = 0 } // TESTING if rl.IsMouseButtonPressed(.LEFT) { mouse_pos := rl.GetMousePosition() screen_space := window_to_screen(mouse_pos) x := screen_to_world(screen_space, camera) fmt.printf("Mouse pos -> world pos: %v\n", x) v := world_to_screen(x, camera) fmt.printf("world pos -> screen pos: %v\n", v) y := world_to_grid(x) fmt.printf("Mouse pos -> grid coord: %v\n", y) z := grid_to_world(y[0], y[1]) fmt.printf("grid pos -> world pos: %v\n", z) } player.state = moving ? .WALK : .IDLE animation_play(&player.animation, &assets.clips[player.state]) animation_update(&player.animation, dt) } draw_player :: proc(player: ^Player) { clip := player.animation.clip src_rect := animation_frame_rect(&player.animation) if player.flipped { src_rect.width = -src_rect.width } dst_rect := rl.Rectangle{ x = player.position.x, y = player.position.y, width = f32(clip.frame_width), height = f32(clip.frame_height), } rl.DrawTexturePro(clip.texture, src_rect, dst_rect, rl.Vector2{}, 0, rl.WHITE) }