physics.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. use crate::com::{Blocking, Collision, Position, Velocity};
  2. use crate::game::MyGame;
  3. use crate::types::{BPhase, NPhase};
  4. use nalgebra::{Isometry2, Vector2};
  5. use ncollide2d::broad_phase::{
  6. broad_phase::BroadPhase, broad_phase::BroadPhaseProxyHandle, BroadPhaseInterferenceHandler,
  7. };
  8. use specs::{Join, RunNow};
  9. struct InterferenceHandler<'a> {
  10. collisions: specs::WriteStorage<'a, Collision>,
  11. }
  12. impl<'a> BroadPhaseInterferenceHandler<specs::Entity> for InterferenceHandler<'a> {
  13. fn is_interference_allowed(&mut self, a: &specs::Entity, b: &specs::Entity) -> bool {
  14. // Prevent self-collision.
  15. *a != *b
  16. }
  17. fn interference_started(&mut self, a: &specs::Entity, b: &specs::Entity) {
  18. self.collisions.get_mut(*a).map(|r| r.has_collision = true);
  19. self.collisions.get_mut(*b).map(|r| r.has_collision = true);
  20. }
  21. fn interference_stopped(&mut self, _: &specs::Entity, _: &specs::Entity) {}
  22. }
  23. struct Collide;
  24. impl<'a> specs::System<'a> for Collide {
  25. type SystemData = (
  26. specs::Entities<'a>,
  27. specs::ReadStorage<'a, Position>,
  28. specs::ReadStorage<'a, Velocity>,
  29. specs::ReadStorage<'a, Blocking>,
  30. specs::WriteStorage<'a, Collision>,
  31. specs::WriteExpect<'a, BPhase>,
  32. specs::WriteExpect<'a, NPhase>,
  33. );
  34. fn run(
  35. &mut self,
  36. (entities, position, velocity, blocking, mut collisions, mut bf, _narrow): Self::SystemData,
  37. ) {
  38. let _: Vec<()> = (&mut collisions)
  39. .join()
  40. .map(|c| c.has_collision = false)
  41. .collect();
  42. let handles: Vec<BroadPhaseProxyHandle> = (&entities, &position, &blocking)
  43. .join()
  44. .map(|(e, pos, bl)| {
  45. let np = if let Some(vel) = velocity.get(e) {
  46. pos.moved(vel)
  47. } else {
  48. pos.clone()
  49. };
  50. bf.create_proxy(
  51. bl.volume
  52. .aabb(&Isometry2::new(Vector2::new(np.x, np.y), nalgebra::zero())),
  53. e,
  54. )
  55. })
  56. .collect();
  57. bf.update(&mut InterferenceHandler {
  58. collisions: collisions,
  59. });
  60. bf.remove(&handles, &mut |_, _| {});
  61. }
  62. }
  63. struct Intersection;
  64. impl<'a> specs::System<'a> for Intersection {
  65. type SystemData = (
  66. specs::Entities<'a>,
  67. specs::ReadStorage<'a, Position>,
  68. specs::ReadStorage<'a, Velocity>,
  69. specs::ReadStorage<'a, Blocking>,
  70. specs::WriteStorage<'a, Collision>,
  71. );
  72. fn run(&mut self, (entity, position, velocity, blocking, mut collision): Self::SystemData) {
  73. let mut spacemap = std::collections::HashMap::new();
  74. for (e, pos, _) in (&entity, &position, &blocking).join() {
  75. spacemap.insert(pos.to_grid(), e);
  76. }
  77. for (pos, vel, col) in (&position, &velocity, &mut collision).join() {
  78. if let Some(_) = spacemap.get(&pos.moved(vel).to_grid()) {
  79. col.has_collision = true;
  80. }
  81. }
  82. }
  83. }
  84. struct Physics;
  85. impl<'a> specs::System<'a> for Physics {
  86. type SystemData = (
  87. specs::ReadStorage<'a, Velocity>,
  88. specs::ReadStorage<'a, Collision>,
  89. specs::WriteStorage<'a, Position>,
  90. );
  91. fn run(&mut self, (velocity, collision, mut position): Self::SystemData) {
  92. for (vel, col, pos) in (&velocity, &collision, &mut position).join() {
  93. if !col.has_collision {
  94. pos.x += vel.dx;
  95. pos.y += vel.dy;
  96. }
  97. }
  98. }
  99. }
  100. struct ResetCollision;
  101. impl<'a> specs::System<'a> for ResetCollision {
  102. type SystemData = specs::WriteStorage<'a, Collision>;
  103. fn run(&mut self, mut collision: Self::SystemData) {
  104. for mut e in (&mut collision).join() {
  105. e.has_collision = false;
  106. }
  107. }
  108. }
  109. pub fn systems(game: &mut MyGame) {
  110. Collide.run_now(&game.world);
  111. // Intersection.run_now(&game.world.res);
  112. Physics.run_now(&game.world);
  113. ResetCollision.run_now(&game.world);
  114. }