use macroquad::prelude::*; const MOVE_SPEED: f32 = 1.0; const LOOK_SPEED: f32 = 0.01; pub struct FirstPersonCamera { pub position: Vec3, yaw: f32, pitch: f32, pub front: Vec3, pub right: Vec3, pub up: Vec3, world_up: Vec3, grabbed: bool, last_mouse: Vec2, } impl FirstPersonCamera { pub fn new(position: Vec3) -> Self { let yaw: f32 = 0.0; let pitch: f32 = -0.25; let world_up = vec3(0.0, 1.0, 0.0); let front = vec3( yaw.cos() * pitch.cos(), pitch.sin(), yaw.sin() * pitch.cos(), ) .normalize(); let right = front.cross(world_up).normalize(); let up = right.cross(front).normalize(); let grabbed = true; set_cursor_grab(grabbed); show_mouse(!grabbed); Self { position, yaw, pitch, front, right, up, world_up, grabbed, last_mouse: mouse_position().into(), } } pub fn update_vectors(&mut self) { self.front = vec3( self.yaw.cos() * self.pitch.cos(), self.pitch.sin(), self.yaw.sin() * self.pitch.cos(), ) .normalize(); self.right = self.front.cross(self.world_up).normalize(); self.up = self.right.cross(self.front).normalize(); } pub fn handle_mouse(&mut self, delta: f32) { let mouse: Vec2 = mouse_position().into(); let mouse_delta = mouse - self.last_mouse; self.last_mouse = mouse; if !self.grabbed { return; } self.yaw += mouse_delta.x * delta * LOOK_SPEED; self.pitch -= mouse_delta.y * delta * LOOK_SPEED; // clamp pitch self.pitch = self.pitch.clamp(-1.5, 1.5); self.update_vectors(); } pub fn handle_keyboard(&mut self) { if is_key_down(KeyCode::W) { self.position += self.front * MOVE_SPEED; } if is_key_down(KeyCode::S) { self.position -= self.front * MOVE_SPEED; } if is_key_down(KeyCode::A) { self.position -= self.right * MOVE_SPEED; } if is_key_down(KeyCode::D) { self.position += self.right * MOVE_SPEED; } if is_key_down(KeyCode::LeftShift) { self.position += Vec3::Y * MOVE_SPEED; } if is_key_down(KeyCode::LeftControl) { self.position -= Vec3::Y * MOVE_SPEED; } } pub fn update(&mut self, delta: f32) { if is_key_pressed(KeyCode::Tab) { self.grabbed = !self.grabbed; set_cursor_grab(self.grabbed); show_mouse(!self.grabbed); } self.handle_keyboard(); self.handle_mouse(delta); } pub fn apply(&self) { set_camera(&Camera3D { position: self.position, up: self.up, target: self.position + self.front, ..Default::default() }); } }