summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gfx.rs73
-rw-r--r--src/gfx/camera.rs119
-rw-r--r--src/gfx/debug_menu.rs13
-rw-r--r--src/main.rs1
-rw-r--r--src/net.rs5
5 files changed, 154 insertions, 57 deletions
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::<f32>::from(pitch).0;
- camera.first_person.yaw = Rad::<f32>::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<f32>,
+ pub rot: Euler<Deg<f32>>,
+ pub speed: f32,
pub fov: Rad<f32>,
pub view: Matrix4<f32>,
pub proj: Matrix4<f32>,
pub frustum: Frustum<f32>,
- pub first_person: FirstPerson,
pub uniform: MatrixUniform,
pub layout: wgpu::BindGroupLayout,
+ pub input: CameraInput,
+}
+
+pub trait ToNative {
+ fn to_native(self) -> Self;
+}
+
+impl<T> ToNative for Euler<T>
+where
+ T: From<Deg<f32>> + std::ops::Add<T, Output = T> + std::ops::Neg<Output = T>,
+{
+ 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<u16, mt_net::NodeDef>),
MapBlock(Point3<i16>, Box<mt_net::MapBlock>),
PlayerPos(Point3<f32>, Deg<f32>, Deg<f32>),
+ 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();
+ }
_ => {}
}
}