diff --git a/src/aabb.rs b/src/aabb.rs index d78ba82..856d98c 100644 --- a/src/aabb.rs +++ b/src/aabb.rs @@ -1,8 +1,14 @@ -use cgmath::Point3; +use std::ops::Sub; +use cgmath::{Point3, Vector3}; +use itertools::Itertools; + +type T = f32; + +#[derive(Debug)] pub struct Aabb { - pub min: Point3, - pub max: Point3, + pub min: Point3, + pub max: Point3, } impl Aabb { @@ -11,6 +17,19 @@ impl Aabb { && (self.min.y <= other.max.y && self.max.y >= other.min.y) && (self.min.z <= other.max.z && self.max.z >= other.min.z) } + + pub fn get_corners(&self) -> [Point3; 8] { + [ + Point3::new(self.min.x, self.min.y, self.min.z), + Point3::new(self.min.x, self.min.y, self.max.z), + Point3::new(self.min.x, self.max.y, self.min.z), + Point3::new(self.min.x, self.max.y, self.max.z), + Point3::new(self.max.x, self.min.y, self.min.z), + Point3::new(self.max.x, self.min.y, self.max.z), + Point3::new(self.max.x, self.max.y, self.min.z), + Point3::new(self.max.x, self.max.y, self.max.z), + ] + } } impl Default for Aabb { diff --git a/src/camera.rs b/src/camera.rs index 7d48629..6b3573e 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -1,5 +1,7 @@ use cgmath::{Matrix4, Point3, Rad, Vector3}; +use crate::aabb::Aabb; + #[rustfmt::skip] pub const OPENGL_TO_WGPU_MATRIX: Matrix4 = Matrix4::new( 1.0, 0.0, 0.0, 0.0, diff --git a/src/state/world_state.rs b/src/state/world_state.rs index 00d7e70..77a7f69 100644 --- a/src/state/world_state.rs +++ b/src/state/world_state.rs @@ -1,6 +1,6 @@ use std::time::Duration; -use cgmath::{InnerSpace, Point3, Rad, Vector3}; +use cgmath::{ElementWise, InnerSpace, Point3, Rad, Vector3}; use wgpu::{ util::{BufferInitDescriptor, DeviceExt}, CommandEncoder, SwapChainTexture, @@ -11,6 +11,7 @@ use winit::{ }; use crate::{ + aabb::Aabb, camera::{Camera, Projection}, render_context::RenderContext, renderable::Renderable, @@ -378,13 +379,24 @@ impl WorldState { } fn check_collision(&self, position: Point3) -> bool { - self.world - .get_block( - position.x as isize, - (position.y - 1.8) as isize, - position.z as isize, - ) - .is_some() + let aabb = Aabb { + min: position + Vector3::new(-0.3, -1.8, -0.3), + max: position + Vector3::new(0.3, 0.0, 0.3), + }; + + for corner in &aabb.get_corners() { + let block = self.world.get_block( + corner.x.floor() as isize, + corner.y.floor() as isize, + corner.z.floor() as isize, + ); + + if block.is_some() { + return true; + } + } + + false } fn update_position(&mut self, dt: Duration) { @@ -393,29 +405,52 @@ impl WorldState { let speed = 10.0 * (self.sprinting as i32 * 2 + 1) as f32; - let mut new_position = self.camera.position; - - let up = Vector3::unit_y() * self.up_speed * speed * dt_seconds; - new_position += up; - if !self.creative && self.check_collision(new_position) { - new_position -= up; - self.up_speed = 0.0; - } - let forward_speed = self.forward_pressed as i32 - self.backward_pressed as i32; - let forward = Vector3::new(yaw_cos, 0.0, yaw_sin).normalize(); - let forward = forward * forward_speed as f32 * speed * dt_seconds; - new_position += forward; - if !self.creative && self.check_collision(new_position) { - new_position -= forward; - } + let forward = Vector3::new(yaw_cos, 0.0, yaw_sin); + let forward = forward * forward_speed as f32; let right_speed = self.right_pressed as i32 - self.left_pressed as i32; - let right = Vector3::new(-yaw_sin, 0.0, yaw_cos).normalize(); - let right = right * right_speed as f32 * speed * dt_seconds; - new_position += right; - if !self.creative && self.check_collision(new_position) { - new_position -= right; + let right = Vector3::new(-yaw_sin, 0.0, yaw_cos); + let right = right * right_speed as f32; + + let mut velocity = forward + right; + if velocity.magnitude2() > 1.0 { + velocity = velocity.normalize(); + } + velocity *= speed * dt.as_secs_f32(); + + let mut new_position = self.camera.position; + + // y component (jumping) + new_position.y += self.up_speed * speed * dt_seconds; + while self.check_collision(new_position) { + self.up_speed = 0.0; + + if velocity.y <= -0.0 { + new_position.y = (new_position.y - 1.8).floor() + 2.8; + } else { + new_position.y = (new_position.y - 0.0001).ceil() - 1.0001; + } + } + + // x component + new_position.x += velocity.x; + while self.check_collision(new_position) { + if velocity.x <= -0.0 { + new_position.x = (new_position.x - 0.2999).floor() + 1.3; + } else { + new_position.x = (new_position.x + 0.3).ceil() - 1.3001; + } + } + + // z component + new_position.z += velocity.z; + while self.check_collision(new_position) { + if velocity.z <= -0.0 { + new_position.z = (new_position.z - 0.2999).floor() + 1.3; + } else { + new_position.z = (new_position.z + 0.3).ceil() - 1.3001; + } } self.camera.position = new_position; diff --git a/src/world/mod.rs b/src/world/mod.rs index 7c46f06..a555053 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -10,7 +10,6 @@ use std::{ use crate::{ camera::Camera, - geometry::GeometryBuffers, npc::Npc, render_context::RenderContext, renderable::Renderable, @@ -342,7 +341,7 @@ impl World { let mut face; - while lengths.magnitude() < 100.0 { + while lengths.magnitude2() < 100.0_f32.powi(2) { if lengths.x < lengths.y && lengths.x < lengths.z { lengths.x += scale.x; position.x += step.x;