Commit e3d8b183 authored by Rahix's avatar Rahix 🦀
Browse files

player-movement: Collide with colliders

Don't move the player if it is colliding with the world
parent e54952e3
......@@ -5,7 +5,7 @@ use ncollide2d::shape;
use std::sync::mpsc;
pub struct Collider {
handle: Option<ncollide2d::pipeline::CollisionObjectSlabHandle>,
pub handle: Option<ncollide2d::pipeline::CollisionObjectSlabHandle>,
drop_notifier: Option<mpsc::SyncSender<ncollide2d::pipeline::CollisionObjectSlabHandle>>,
shape: shape::ShapeHandle<f32>,
groups: pipeline::CollisionGroups,
......@@ -55,7 +55,7 @@ impl Drop for Collider {
}
pub struct CollisionWorld {
world: ncollide2d::world::CollisionWorld<f32, legion::Entity>,
pub world: ncollide2d::world::CollisionWorld<f32, legion::Entity>,
drop_notifier: mpsc::SyncSender<ncollide2d::pipeline::CollisionObjectSlabHandle>,
drop_receiver: mpsc::Receiver<ncollide2d::pipeline::CollisionObjectSlabHandle>,
}
......
use crate::colliders;
use crate::components;
pub fn create_player(world: &mut legion::World) -> legion::Entity {
world.push((
components::Player,
components::Position::new(600.0, 600.0),
components::Position::new(800.0, 800.0),
components::Movable::new(),
colliders::Collider::new_circle_collider(50.0),
))
}
use crate::colliders;
use crate::components;
use crate::resources;
use legion::IntoQuery;
......@@ -17,8 +18,30 @@ pub fn move_camera_to_player(
#[legion::system(for_each)]
pub fn move_movable(
position: &mut components::Position,
movable: &components::Movable,
movable: &mut components::Movable,
collider: &colliders::Collider,
#[resource] clock: &resources::Clock,
#[resource] collision_world: &colliders::CollisionWorld,
) {
position.0 += movable.velocity * clock.frame_delta();
let mut actual_velocity = movable.velocity.clone();
// First, check if the entity is colliding. If so, zero out its movement "into" the collision
// before advancing the position.
for pair in collision_world
.world
.contacts_with(collider.handle.unwrap(), false)
.unwrap()
{
if let Some(contact) = pair.3.deepest_contact() {
// Length of the projection of the velocity onto the normal. If it's greater than 0,
// we're moving "into" the collider and thus, this component of the velocity should be
// zeroed out.
let d: f32 = contact.contact.normal.dot(&actual_velocity);
if d > 0.0 {
actual_velocity -= contact.contact.normal.into_inner() * d;
}
}
}
position.0 += actual_velocity * clock.frame_delta();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment