From 63d0c704e889f0b05f03f39903378324ca5b6431 Mon Sep 17 00:00:00 2001 From: Lizzy Fleckenstein Date: Wed, 24 May 2023 02:34:27 +0200 Subject: Respect server-sent movement settings --- src/gfx.rs | 73 +++++++++++++++++++------------ src/gfx/camera.rs | 119 +++++++++++++++++++++++++++++++++++++++++--------- src/gfx/debug_menu.rs | 13 ++---- src/main.rs | 1 + src/net.rs | 5 +++ 5 files changed, 154 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/gfx.rs b/src/gfx.rs index c465baa..2c4a219 100644 --- a/src/gfx.rs +++ b/src/gfx.rs @@ -1,11 +1,11 @@ use crate::{GfxEvent::*, NetEvent}; -use cgmath::Rad; use std::time::Instant; use tokio::sync::mpsc; use winit::{ event::{DeviceEvent::*, Event::*, WindowEvent::*}, event_loop::ControlFlow::ExitWithCode, platform::run_return::EventLoopExtRunReturn, + window::CursorGrabMode, }; mod camera; @@ -38,6 +38,22 @@ pub async fn run( let mut fps_counter = fps_counter::FPSCounter::new(); let mut game_paused = false; + let update_cursor_mode = |game_paused| { + let modes: &[CursorGrabMode] = if game_paused { + &[CursorGrabMode::None] + } else { + &[CursorGrabMode::Confined, CursorGrabMode::Locked] + }; + + for mode in modes { + if window.set_cursor_grab(*mode).is_ok() { + return; + } + } + }; + + update_cursor_mode(game_paused); + event_loop.run_return(|event, _, flow| match event { MainEventsCleared => window.request_redraw(), RedrawRequested(id) if id == window.id() => { @@ -52,11 +68,7 @@ pub async fn run( } net_events - .send(NetEvent::PlayerPos( - camera.first_person.position.into(), - Rad(camera.first_person.yaw).into(), - Rad(camera.first_person.pitch).into(), - )) + .send(NetEvent::PlayerPos(camera.pos, camera.rot.y, camera.rot.z)) .ok(); let mut render = || { @@ -91,6 +103,7 @@ pub async fn run( event, window_id: id, } if id == window.id() => match event { + Focused(false) => camera.input = Default::default(), CloseRequested => *flow = ExitWithCode(0), Resized(size) | ScaleFactorChanged { @@ -109,12 +122,20 @@ pub async fn run( }, .. } => { - use fps_camera::Actions; use winit::event::{ElementState, VirtualKeyCode as Key}; if key == Key::Escape && key_state == ElementState::Pressed { game_paused = !game_paused; window.set_cursor_visible(game_paused); + update_cursor_mode(game_paused); + + if game_paused { + camera.input = Default::default(); + } + } + + if game_paused { + return; } if key == Key::F3 && key_state == ElementState::Pressed { @@ -122,20 +143,15 @@ pub async fn run( } if !game_paused { - let actions = match key { - Key::W => Actions::MOVE_FORWARD, - Key::A => Actions::STRAFE_LEFT, - Key::S => Actions::MOVE_BACKWARD, - Key::D => Actions::STRAFE_RIGHT, - Key::Space => Actions::FLY_UP, - Key::LShift => Actions::FLY_DOWN, - _ => Actions::empty(), - }; - - match key_state { - ElementState::Pressed => camera.first_person.enable_actions(actions), - ElementState::Released => camera.first_person.disable_action(actions), - } + *(match key { + Key::W => &mut camera.input.forward, + Key::A => &mut camera.input.left, + Key::S => &mut camera.input.backward, + Key::D => &mut camera.input.right, + Key::Space => &mut camera.input.jump, + Key::LShift => &mut camera.input.sneak, + _ => return, + }) = key_state == ElementState::Pressed; } } _ => {} @@ -145,9 +161,9 @@ pub async fn run( .. } => { if !game_paused { - camera - .first_person - .update_mouse(-delta.0 as f32, delta.1 as f32); + camera.input.mouse_x += delta.0 as f32; + camera.input.mouse_y += delta.1 as f32; + window .set_cursor_position(winit::dpi::PhysicalPosition::new( gpu.config.width / 2, @@ -179,9 +195,12 @@ pub async fn run( } } PlayerPos(pos, pitch, yaw) => { - camera.first_person.position = pos.into(); - camera.first_person.pitch = Rad::::from(pitch).0; - camera.first_person.yaw = Rad::::from(yaw).0; + camera.pos = pos; + camera.rot.y = yaw; + camera.rot.z = pitch; + } + MovementSpeed(speed) => { + camera.speed = speed; } }, _ => {} diff --git a/src/gfx/camera.rs b/src/gfx/camera.rs index 874c9fc..32d39ad 100644 --- a/src/gfx/camera.rs +++ b/src/gfx/camera.rs @@ -1,57 +1,134 @@ use super::{gpu::Gpu, util::MatrixUniform}; -use cgmath::{prelude::*, Deg, Matrix4, Rad}; +use cgmath::{prelude::*, Deg, Euler, Matrix3, Matrix4, Point3, Rad, Vector3}; use collision::Frustum; -use fps_camera::{FirstPerson, FirstPersonSettings}; use std::time::Duration; +#[derive(Default)] +pub struct CameraInput { + pub forward: bool, + pub left: bool, + pub backward: bool, + pub right: bool, + pub jump: bool, + pub sneak: bool, + pub mouse_x: f32, + pub mouse_y: f32, +} + pub struct Camera { + pub pos: Point3, + pub rot: Euler>, + pub speed: f32, pub fov: Rad, pub view: Matrix4, pub proj: Matrix4, pub frustum: Frustum, - pub first_person: FirstPerson, pub uniform: MatrixUniform, pub layout: wgpu::BindGroupLayout, + pub input: CameraInput, +} + +pub trait ToNative { + fn to_native(self) -> Self; +} + +impl ToNative for Euler +where + T: From> + std::ops::Add + std::ops::Neg, +{ + fn to_native(mut self) -> Self { + self.y = -self.y + Deg(270.0).into(); + self.z = -self.z; + self + } } impl Camera { pub fn new(gpu: &Gpu) -> Self { - let first_person = FirstPerson::new( - [0.0, 0.0, 0.0], - FirstPersonSettings { - speed_horizontal: 10.0, - speed_vertical: 10.0, - mouse_sensitivity_horizontal: 1.0, - mouse_sensitivity_vertical: 1.0, - }, - ); - let layout = MatrixUniform::layout(&gpu.device, "camera"); let uniform = MatrixUniform::new(&gpu.device, &layout, Matrix4::identity(), "camera", true); Self { + pos: Point3::new(0.0, 0.0, 0.0), + rot: Euler { + x: Deg(0.0), + y: Deg(0.0), + z: Deg(0.0), + }, + speed: 0.0, fov: Deg(90.0).into(), proj: Matrix4::identity(), view: Matrix4::identity(), frustum: Frustum::from_matrix4(Matrix4::identity()).unwrap(), - first_person, uniform, layout, + input: Default::default(), } } pub fn update(&mut self, gpu: &Gpu, dt: Duration) { - self.first_person.yaw += Rad::from(Deg(180.0)).0; - self.first_person.yaw *= -1.0; + let dt = dt.as_secs_f32(); + + let sensitivity = dt * 2.0; + + self.rot.y += Deg(sensitivity * self.input.mouse_x); + self.rot.z += Deg(sensitivity * self.input.mouse_y); + self.rot.z.0 = self.rot.z.0.min(89.9).max(-89.9); + + self.input.mouse_x = 0.0; + self.input.mouse_y = 0.0; + + let rot = Matrix3::from(self.rot.to_native()); - let cam = self.first_person.camera(dt.as_secs_f32()); + let forward = rot * Vector3::unit_x(); + let up = rot * Vector3::unit_y(); - self.first_person.yaw *= -1.0; - self.first_person.yaw -= Rad::from(Deg(180.0)).0; + { + let mut forward = forward; + let mut up = up; + let mut right = forward.cross(up); - self.first_person.position = cam.position; + let pitch_move = false; + + if !pitch_move { + forward.y = 0.0; + right.y = 0.0; + up = Vector3::unit_y(); + } + + let mut hdir = Vector3::zero(); + let mut vdir = Vector3::zero(); + + if self.input.forward { + hdir += forward; + } + if self.input.backward { + hdir -= forward; + } + if self.input.right { + hdir += right; + } + if self.input.left { + hdir -= right; + } + if self.input.jump { + vdir += up; + } + if self.input.sneak { + vdir -= up; + } + + self.pos += self.speed + * dt + * (vdir + + if hdir.is_zero() { + hdir + } else { + hdir.normalize() + }); + } - self.view = Matrix4::from(cam.orthogonal()); + self.view = Matrix4::look_at_dir(self.pos, forward, up); self.uniform.set(&gpu.queue, self.proj * self.view); } diff --git a/src/gfx/debug_menu.rs b/src/gfx/debug_menu.rs index daca08d..4baf0f1 100644 --- a/src/gfx/debug_menu.rs +++ b/src/gfx/debug_menu.rs @@ -1,5 +1,4 @@ use super::{camera::Camera, font::Font}; -use cgmath::{Deg, Rad}; use wgpu_glyph::{Section, Text}; pub struct DebugMenu { @@ -37,21 +36,17 @@ impl DebugMenu { offset += 20.0; }; - let angle = |x| Deg::from(Rad(x)).0; - - let pos = camera.first_person.position; - add_text(&format!( "{} {}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION") )); add_text(&format!("{} FPS", self.fps)); - add_text(&format!("({:.1}, {:.1}, {:.1})", pos[0], pos[1], pos[2])); add_text(&format!( - "yaw: {:.1}°", - (angle(camera.first_person.yaw) + 360.0) % 360.0 + "({:.1}, {:.1}, {:.1})", + camera.pos.x, camera.pos.y, camera.pos.z )); - add_text(&format!("pitch: {:.1}°", angle(camera.first_person.pitch))); + add_text(&format!("yaw: {:.1}°", (camera.rot.y.0 + 360.0) % 360.0)); + add_text(&format!("pitch: {:.1}°", camera.rot.z.0)); } } diff --git a/src/main.rs b/src/main.rs index 759a5bf..037cacb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,7 @@ pub enum GfxEvent { NodeDefs(HashMap), MapBlock(Point3, Box), PlayerPos(Point3, Deg, Deg), + MovementSpeed(f32), } #[derive(Debug, Clone)] diff --git a/src/net.rs b/src/net.rs index 78597c1..2598651 100644 --- a/src/net.rs +++ b/src/net.rs @@ -245,6 +245,11 @@ impl Conn { ChatMsg { text, .. } => { println!("{text}"); } + Movement { walk_speed, .. } => { + self.events + .send_event(GfxEvent::MovementSpeed(walk_speed)) + .ok(); + } _ => {} } } -- cgit v1.2.3