diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index e6d64dea73..7ac4b0c470 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -156,19 +156,26 @@ impl<'a> System<'a> for Sys { vel.0 = integrate_forces(dt.0, vel.0, friction); // Basic collision with terrain + let player_rad = 0.3; // half-width of the player's AABB + let player_height = 1.7; // Iterate through nearby blocks, prioritise closer ones let near_iter = (0..5) - .map(move |dist| (-dist..=dist) - .map(move |x| (-dist..=dist) - .map(move |y| (-dist..=dist) - .map(move |z| Vec3::new(x, y, z)) - .filter(move |p| p.map(|e: i32| e.abs()).reduce_max() == dist) - .map(|p| p.into_tuple())))) + .map(move |dist| { + (-dist..=dist).map(move |x| { + (-dist..=dist).map(move |y| { + (-dist..=dist) + .map(move |z| Vec3::new(x, y, z)) + .filter(move |p| p.map(|e: i32| e.abs()).reduce_max() == dist) + .map(|p| p.into_tuple()) + }) + }) + }) .flatten() .flatten() .flatten(); + // Function for determining whether the player at a specific position collides with the ground let collision_with = |pos: Vec3, near_iter| { for (i, j, k) in near_iter { let block_pos = pos.map(|e| e.floor() as i32) + Vec3::new(i, j, k); @@ -178,8 +185,14 @@ impl<'a> System<'a> for Sys { .map(|vox| !vox.is_empty()) .unwrap_or(false) { - let this_aabb = Aabb { min: pos + Vec3::new(-0.3, -0.3, 0.0), max: pos + Vec3::new(0.3, 0.3, 1.7) }; - let block_aabb = Aabb { min: block_pos.map(|e| e as f32), max: block_pos.map(|e| e as f32) + 1.0 }; + let this_aabb = Aabb { + min: pos + Vec3::new(-player_rad, -player_rad, 0.0), + max: pos + Vec3::new(player_rad, player_rad, player_height), + }; + let block_aabb = Aabb { + min: block_pos.map(|e| e as f32), + max: block_pos.map(|e| e as f32) + 1.0, + }; if this_aabb.collides_with_aabb(block_aabb) { return true; @@ -204,8 +217,14 @@ impl<'a> System<'a> for Sys { .unwrap_or(false) { // ...and calculate bounding boxes for both the player's body and the block. - let this_aabb = Aabb { min: pos.0 + Vec3::new(-0.3, -0.3, 0.0), max: pos.0 + Vec3::new(0.3, 0.3, 1.7) }; - let block_aabb = Aabb { min: block_pos.map(|e| e as f32), max: block_pos.map(|e| e as f32) + 1.0 }; + let this_aabb = Aabb { + min: pos.0 + Vec3::new(-player_rad, -player_rad, 0.0), + max: pos.0 + Vec3::new(player_rad, player_rad, player_height), + }; + let block_aabb = Aabb { + min: block_pos.map(|e| e as f32), + max: block_pos.map(|e| e as f32) + 1.0, + }; // If the bounding boxes collide, resolve the collision if this_aabb.collides_with_aabb(block_aabb) { @@ -219,12 +238,16 @@ impl<'a> System<'a> for Sys { on_ground = true; } - if resolve_dir.z == 0.0 && !collision_with(pos.0 + Vec3::unit_z() * 1.0, near_iter.clone()) { + if resolve_dir.z == 0.0 + && !collision_with(pos.0 + Vec3::unit_z() * 1.0, near_iter.clone()) + { pos.0.z += 1.0; break; } else { pos.0 += resolve_dir; - vel.0 = vel.0.map2(resolve_dir, |e, d| if d == 0.0 { e } else { 0.0 }); + vel.0 = vel + .0 + .map2(resolve_dir, |e, d| if d == 0.0 { e } else { 0.0 }); } } } @@ -232,7 +255,10 @@ impl<'a> System<'a> for Sys { if on_ground { on_grounds.insert(entity, OnGround); - } else if collision_with(pos.0 - Vec3::unit_z() * 1.0, near_iter.clone()) && vel.0.z < 0.0 && vel.0.z > -1.0 { + } else if collision_with(pos.0 - Vec3::unit_z() * 1.0, near_iter.clone()) + && vel.0.z < 0.0 + && vel.0.z > -1.0 + { pos.0.z = (pos.0.z - 0.05).floor(); on_grounds.insert(entity, OnGround); }