gdritter repos wenaglia / 86edfda
Clunkily use a collision world instead of manual broad phase Getty Ritter 4 years ago
5 changed file(s) with 67 addition(s) and 74 deletion(s). Collapse all Expand all
11 use specs::world::WorldExt;
22 use specs::{Component, NullStorage, VecStorage};
3 use crate::types::World;
34
45 /// Register all the components with the world.
56 pub fn register(world: &mut specs::World) {
112113 #[derive(Component)]
113114 #[storage(VecStorage)]
114115 pub struct Blocking {
115 pub volume: Box<dyn ncollide2d::shape::Shape<f32>>,
116 pub handle: ncollide2d::pipeline::CollisionObjectSlabHandle,
116117 }
117118
118119 impl Blocking {
119 pub fn new() -> Blocking {
120 Default::default()
120 pub fn new_shape<S: ncollide2d::shape::Shape<f32>>(w: &mut World, volume: S) -> Blocking {
121 let (handle, _) = w.add(
122 nalgebra::geometry::Isometry::identity(),
123 ncollide2d::shape::ShapeHandle::new(volume),
124 ncollide2d::pipeline::CollisionGroups::new(),
125 ncollide2d::pipeline::object::GeometricQueryType::Proximity(0.0),
126 None,
127 );
128 Blocking {
129 handle,
130 }
131 }
132
133 pub fn new_box(w: &mut World) -> Blocking {
134 Blocking::new_shape(w, ncollide2d::shape::Cuboid::new(nalgebra::Vector2::new(
135 11.0, 11.0,
136 )))
137 }
138
139 pub fn new_ball(w: &mut World) -> Blocking {
140 Blocking::new_shape(w, ncollide2d::shape::Ball::new(8.0))
121141 }
122142 }
123
124 impl Default for Blocking {
125 fn default() -> Blocking {
126 Blocking {
127 volume: Box::new(ncollide2d::shape::Cuboid::new(nalgebra::Vector2::new(
128 11.0, 11.0,
129 ))),
130 }
131 }
132 }
6060 let mut world = specs::World::new();
6161 com::register(&mut world);
6262
63 world.insert(ncollide2d::world::CollisionWorld::<f32, Option<specs::Entity>>::new(0.1));
6364 res::world_from_file(&mut world, "assets/main.tmx");
6465
6566 // Make a Context and an EventLoop.
8384 world.insert(sprites);
8485 world.insert(res::KeySet::new());
8586
86 let broad_phase: types::BPhase = nc::DBVTBroadPhase::new(0.0f32);
87 world.insert(broad_phase);
88
89 let narrow_phase: types::NPhase = nc::NarrowPhase::new(
90 Box::new(nc::DefaultContactDispatcher::new()),
91 Box::new(nc::DefaultProximityDispatcher::new()),
92 );
93 world.insert(narrow_phase);
94
9587 let mut my_game = MyGame { world };
9688
9789 event::run(&mut ctx, &mut evloop, &mut my_game)
11 use crate::com::*;
22 use crate::consts;
3 use crate::types::World;
34
45 use specs::world::{Builder, WorldExt};
56 use std::path::Path;
5556 let y = y as f32 * consts::TILE_SIZE;
5657 let u = ((n - 1) % 32) as u8;
5758 let v = ((n - u as u32 - 1) / 32) as u8;
59 let blocking = if tilesets[0].tiles[(n-1) as usize].properties["pass"]
60 == tiled::PropertyValue::BoolValue(false) {
61 let mut h = w.write_resource::<World>();
62 Some(Blocking::new_box(&mut h))
63 } else {
64 None
65 };
5866 let mut e = w
5967 .create_entity()
6068 .with(Position { x, y })
6573 DrawLayer::Decoration => e.with(Decoration),
6674 };
6775
68 let e = if tilesets[0].tiles[(n-1) as usize].properties["pass"]
69 == tiled::PropertyValue::BoolValue(false)
70 {
71 e.with(Blocking::new())
72 } else {
73 e
74 };
76 let e = if let Some(b) = blocking { e.with(b) } else { e };
7577 e.build();
7678 }
7779 }
7981 }
8082
8183 // create the player
84 let ball = {
85 let mut h = w.write_resource::<World>();
86 Blocking::new_ball(&mut h)
87 };
8288 w.create_entity()
8389 .with(Position {
8490 x: 3.0 * consts::TILE_SIZE,
9197 .with(Collision {
9298 has_collision: false,
9399 })
94 .with(Blocking {
95 volume: Box::new(ncollide2d::shape::Ball::new(10.0)),
96 })
100 .with(ball)
97101 .build();
98102 }
11 use crate::com::{Blocking, Collision, Position, Velocity};
22 use crate::game::MyGame;
3 use crate::types::{BPhase, NPhase};
3 use crate::types::World;
44
55 use nalgebra::{Isometry2, Vector2};
6 use ncollide2d::broad_phase::{
7 broad_phase::BroadPhase, broad_phase::BroadPhaseProxyHandle, BroadPhaseInterferenceHandler,
8 };
96 use specs::{Join, RunNow};
10
11 struct InterferenceHandler<'a> {
12 collisions: specs::WriteStorage<'a, Collision>,
13 }
14
15 impl<'a> BroadPhaseInterferenceHandler<specs::Entity> for InterferenceHandler<'a> {
16 fn is_interference_allowed(&mut self, a: &specs::Entity, b: &specs::Entity) -> bool {
17 // Prevent self-collision.
18 *a != *b
19 }
20
21 fn interference_started(&mut self, a: &specs::Entity, b: &specs::Entity) {
22 self.collisions.get_mut(*a).map(|r| r.has_collision = true);
23 self.collisions.get_mut(*b).map(|r| r.has_collision = true);
24 }
25
26 fn interference_stopped(&mut self, _: &specs::Entity, _: &specs::Entity) {}
27 }
287
298 struct Collide;
309
3514 specs::ReadStorage<'a, Velocity>,
3615 specs::ReadStorage<'a, Blocking>,
3716 specs::WriteStorage<'a, Collision>,
38 specs::WriteExpect<'a, BPhase>,
39 specs::WriteExpect<'a, NPhase>,
17 specs::WriteExpect<'a, World>,
4018 );
4119
4220 fn run(
4321 &mut self,
44 (entities, position, velocity, blocking, mut collisions, mut bf, _narrow): Self::SystemData,
22 (entities, position, velocity, blocking, mut collisions, mut w): Self::SystemData,
4523 ) {
46 let _: Vec<()> = (&mut collisions)
47 .join()
48 .map(|c| c.has_collision = false)
49 .collect();
50 let handles: Vec<BroadPhaseProxyHandle> = (&entities, &position, &blocking)
24 let _: Vec<()> = (&entities, &position, &blocking)
5125 .join()
5226 .map(|(e, pos, bl)| {
5327 let np = if let Some(vel) = velocity.get(e) {
5529 } else {
5630 pos.clone()
5731 };
58 bf.create_proxy(
59 bl.volume
60 .aabb(&Isometry2::new(Vector2::new(np.x, np.y), nalgebra::zero())),
61 e,
62 )
32 let obj = w.get_mut(bl.handle).unwrap();
33 *obj.data_mut() = Some(e);
34 obj.set_position(
35 Isometry2::new(Vector2::new(np.x, np.y), nalgebra::zero()));
6336 })
6437 .collect();
65
66 bf.update(&mut InterferenceHandler {
67 collisions: collisions,
68 });
69
70 bf.remove(&handles, &mut |_, _| {});
38 w.update();
39 for ev in w.proximity_events() {
40 if ev.new_status == ncollide2d::query::Proximity::Intersecting {
41 if let Some(e) = w.collision_object(ev.collider1).unwrap().data() {
42 collisions.get_mut(*e).map(|r| r.has_collision = true);
43 }
44 if let Some(e) = w.collision_object(ev.collider2).unwrap().data() {
45 collisions.get_mut(*e).map(|r| r.has_collision = true);
46 }
47 } else {
48 if let Some(e) = w.collision_object(ev.collider1).unwrap().data() {
49 collisions.get_mut(*e).map(|r| r.has_collision = false);
50 }
51 if let Some(e) = w.collision_object(ev.collider2).unwrap().data() {
52 collisions.get_mut(*e).map(|r| r.has_collision = false);
53 }
54 }
55 }
56 w.clear_events();
7157 }
7258 }
7359
131117 Collide.run_now(&game.world);
132118 // Intersection.run_now(&game.world.res);
133119 Physics.run_now(&game.world);
134 ResetCollision.run_now(&game.world);
120 // ResetCollision.run_now(&game.world);
135121 }
44 specs::Entity,
55 >;
66 pub type NPhase = ncollide2d::narrow_phase::NarrowPhase<f32, ()>;
7 pub type World = ncollide2d::world::CollisionWorld<f32, Option<specs::Entity>>;