浏览代码

Merge branch 'collision' into entity_model

* collision:
  Adding quad-collision detection, and triangle collision detection.
  Start making collision detection. TODO: intersects(quad, quad)
Sam Jaffe 6 年之前
父节点
当前提交
0f1aca5bb1

+ 2 - 0
engine/include/game/engine/engine_fwd.hpp

@@ -11,6 +11,8 @@
 #include <unordered_map>
 
 namespace engine {
+  using collision_t = int;
+
   using raw_key_t = int;
   using key_enum_t = int;
   using scene_id_t = std::string;

+ 3 - 2
engine/include/game/engine/entity.hpp

@@ -20,6 +20,7 @@ namespace engine {
   public:
     entity(Json::Value const & json);
     void update(float delta);
+    void collide(entity const &);
 
     graphics::object const & render_info() const { return render_info_; }
 
@@ -40,7 +41,7 @@ namespace engine {
 
     float scale;
 
-    int collides_with;
-    int collides_as;
+    collision_t collides_with;
+    collision_t collides_as;
   };
 }

+ 5 - 0
engine/include/game/engine/scene.hpp

@@ -43,6 +43,11 @@ namespace engine {
     graphics::renderer * renderer;
     std::vector<entity> entities;
 
+    // Map from entity::collides_with -> [entity*]
+    std::unordered_map<collision_t, std::vector<entity *>> colliders;
+    // Map from entity::collides_as -> [entity*]
+    std::unordered_map<collision_t, std::vector<entity *>> collidables;
+
   private:
     math::vec2 local_scene_dimension_;
     key_binding keys_;

+ 2 - 0
engine/src/entity.cxx

@@ -42,3 +42,5 @@ void entity::update(float delta) {
   velocity += acceleration * delta;
   //  render_info.angle += angular_velocity * delta;
 }
+
+void entity::collide(entity const &) {}

+ 12 - 0
engine/src/scene.cpp

@@ -11,6 +11,7 @@
 #include "game/engine/events.hpp"
 #include "game/engine/game_dispatch.hpp"
 #include "game/graphics/renderer.hpp"
+#include "game/math/common.hpp"
 
 namespace engine {
 
@@ -20,6 +21,17 @@ namespace engine {
     for (auto & ent : entities) {
       ent.update(delta);
     }
+    for (auto & pair : colliders) {
+      auto & collidable = collidables[pair.first];
+      for (auto & ent : pair.second) {
+        for (auto & hit : collidable) {
+          if (math::intersects(ent->render_info().points,
+                               hit->render_info().points)) {
+            ent->collide(*hit);
+          }
+        }
+      }
+    }
   }
 
   void scene::render() {

+ 4 - 0
math/include/game/math/shape.hpp

@@ -25,6 +25,10 @@ namespace math { namespace dim2 {
     float radius;
   };
 
+  struct triangle {
+    point a, b, c;
+  };
+
   struct quad {
     point ll, lr, ur, ul;
   };

+ 23 - 1
math/src/common.cpp

@@ -109,7 +109,29 @@ namespace math {
            contains(lhs, rhs.center);
   }
 
-  bool intersects(dim2::quad const & lhs, dim2::quad const & rhs);
+  bool check_edges(dim2::line const & seg, dim2::triangle const & tri) {
+    return orient(seg, tri.a) == clockwise && orient(seg, tri.b) == clockwise &&
+           orient(seg, tri.c) == clockwise;
+  }
+
+  bool intersects(dim2::triangle const & lhs, dim2::triangle const & rhs) {
+    if (check_edges({lhs.a, lhs.b}, rhs)) return false;
+    if (check_edges({lhs.b, lhs.c}, rhs)) return false;
+    if (check_edges({lhs.c, lhs.a}, rhs)) return false;
+    if (check_edges({rhs.a, rhs.b}, lhs)) return false;
+    if (check_edges({rhs.b, rhs.c}, lhs)) return false;
+    if (check_edges({rhs.c, rhs.a}, lhs)) return false;
+    return true;
+  }
+
+  bool intersects(dim2::quad const & lhs, dim2::quad const & rhs) {
+    dim2::triangle l1{lhs.ll, lhs.lr, lhs.ul};
+    dim2::triangle l2{lhs.ul, lhs.ur, lhs.ll};
+    dim2::triangle r1{rhs.ll, rhs.lr, rhs.ul};
+    dim2::triangle r2{rhs.ul, rhs.ur, rhs.ll};
+    return intersects(l1, r1) || intersects(l2, r2) || intersects(l1, r2) ||
+           intersects(l2, r1);
+  }
 
   bool intersects(dim2::circle const & lhs, dim2::circle const & rhs) {
     vec2 const delta = rhs.center - lhs.center;