use crate::com::{Blocking, Collision, Position, Velocity}; use crate::game::MyGame; use crate::types::World; 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.data_mut() = Some(e); 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 { if let Some(e) = w.collision_object(ev.collider1).unwrap().data() { collisions.get_mut(*e).map(|r| r.has_collision = true); } if let Some(e) = w.collision_object(ev.collider2).unwrap().data() { collisions.get_mut(*e).map(|r| r.has_collision = true); } } else { if let Some(e) = w.collision_object(ev.collider1).unwrap().data() { collisions.get_mut(*e).map(|r| r.has_collision = false); } if let Some(e) = w.collision_object(ev.collider2).unwrap().data() { collisions.get_mut(*e).map(|r| r.has_collision = false); } } } w.clear_events(); } } struct Intersection; impl<'a> specs::System<'a> for Intersection { type SystemData = ( specs::Entities<'a>, specs::ReadStorage<'a, Position>, specs::ReadStorage<'a, Velocity>, specs::ReadStorage<'a, Blocking>, specs::WriteStorage<'a, Collision>, ); fn run(&mut self, (entity, position, velocity, blocking, mut collision): Self::SystemData) { let mut spacemap = std::collections::HashMap::new(); for (e, pos, _) in (&entity, &position, &blocking).join() { spacemap.insert(pos.to_grid(), e); } for (pos, vel, col) in (&position, &velocity, &mut collision).join() { if let Some(_) = spacemap.get(&pos.moved(vel).to_grid()) { col.has_collision = true; } } } } 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; } } } } struct ResetCollision; impl<'a> specs::System<'a> for ResetCollision { type SystemData = specs::WriteStorage<'a, Collision>; fn run(&mut self, mut collision: Self::SystemData) { for mut e in (&mut collision).join() { e.has_collision = false; } } } pub fn systems(game: &mut MyGame) { Collide.run_now(&game.world); // Intersection.run_now(&game.world.res); Physics.run_now(&game.world); // ResetCollision.run_now(&game.world); }