use crate::components::{Blocking, Collision, Position, Velocity, World};
use crate::game::MyGame;
use nalgebra::{Isometry2, Vector2};
use specs::{Join, RunNow};
struct Collide;
impl<'a> specs::System<'a> for Collide {
type SystemData = (
specs::Entities<'a>,
specs::ReadStorage<'a, Position>,
specs::ReadStorage<'a, Velocity>,
specs::ReadStorage<'a, Blocking>,
specs::WriteStorage<'a, Collision>,
specs::WriteExpect<'a, World>,
);
fn run(
&mut self,
(entities, position, velocity, blocking, mut collisions, mut w): Self::SystemData,
) {
let _: Vec<()> = (&entities, &position, &blocking)
.join()
.map(|(e, pos, bl)| {
let np = if let Some(vel) = velocity.get(e) {
pos.moved(vel)
} else {
pos.clone()
};
let obj = w.get_mut(bl.handle).unwrap();
obj.set_position(Isometry2::new(Vector2::new(np.x, np.y), nalgebra::zero()));
})
.collect();
w.update();
for ev in w.proximity_events() {
if ev.new_status == ncollide2d::query::Proximity::Intersecting {
let e = w.collision_object(ev.collider1).unwrap().data();
collisions.get_mut(*e).map(|r| r.has_collision = true);
let e = w.collision_object(ev.collider2).unwrap().data();
collisions.get_mut(*e).map(|r| r.has_collision = true);
} else {
let e = w.collision_object(ev.collider1).unwrap().data();
collisions.get_mut(*e).map(|r| r.has_collision = false);
let e = w.collision_object(ev.collider2).unwrap().data();
collisions.get_mut(*e).map(|r| r.has_collision = false);
}
}
w.clear_events();
}
}
struct Physics;
impl<'a> specs::System<'a> for Physics {
type SystemData = (
specs::ReadStorage<'a, Velocity>,
specs::ReadStorage<'a, Collision>,
specs::WriteStorage<'a, Position>,
);
fn run(&mut self, (velocity, collision, mut position): Self::SystemData) {
for (vel, col, pos) in (&velocity, &collision, &mut position).join() {
if !col.has_collision {
pos.x += vel.dx;
pos.y += vel.dy;
}
}
}
}
pub fn systems(game: &mut MyGame) {
Collide.run_now(&game.world);
Physics.run_now(&game.world);
}