]> git.localhorst.tv Git - sdl-test8.git/blobdiff - src/game/Entity.cpp
added collision engine, more or less stole gameplay from sdl-test7
[sdl-test8.git] / src / game / Entity.cpp
diff --git a/src/game/Entity.cpp b/src/game/Entity.cpp
new file mode 100644 (file)
index 0000000..1c3f785
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Entity.cpp
+ *
+ *  Created on: Apr 25, 2012
+ *      Author: holy
+ */
+
+#include "Entity.h"
+
+#include "../app/Timer.h"
+#include "../geometry/constants.h"
+
+#include <limits>
+
+using geometry::PI;
+using std::numeric_limits;
+
+namespace game {
+
+
+void Entity::Update(const app::Timer &timer) {
+       translation += linearVelocity * timer.DeltaT();
+       rotation += angularVelocity * timer.DeltaT();
+       if (rotation > 2.0 * PI) {
+               rotation -= 2.0 * PI;
+       } else if (rotation < -(2.0 * PI)) {
+               rotation += 2.0 * PI;
+       }
+       shape->Translate(linearVelocity * timer.DeltaT());
+       shape->Rotate(angularVelocity * timer.DeltaT());
+}
+
+bool Entity::CheckCollision(const Entity &other, Ray &ray) {
+       return shape->CheckCollision(*other.shape, ray);
+}
+
+
+Entity::Vector Entity::VelocityAt(const Vector &p) const {
+       if (angularVelocity == 0 || p == translation) return linearVelocity;
+
+       Vector v(linearVelocity);
+       Vector pRelative(p - translation);
+       v += pRelative.Rotate90() * angularVelocity;
+       return v;
+}
+
+
+void Entity::Rotate(Scalar d) {
+       rotation += d;
+       shape->Rotate(d);
+}
+
+void Entity::Translate(const Vector &d) {
+       translation += d;
+       shape->Translate(d);
+}
+
+void Entity::Accelerate(const Vector &dvl, Scalar dva) {
+       linearVelocity += dvl;
+       angularVelocity += dva;
+}
+
+
+void Entity::CollisionResponse(Entity &a, const Ray &na, Entity &b) {
+       if (a.mass == numeric_limits<Scalar>::infinity()
+                       && b.mass == numeric_limits<Scalar>::infinity()) {
+               // special case: collision of two infinitely heavy entities
+               InfInfCollisionResponse(a, na, b);
+               return;
+       }
+
+       const Scalar e(1);
+
+       const Vector va(a.LinearVelocity());
+       const Vector vb(b.LinearVelocity());
+       const Scalar wa(a.AngularVelocity());
+       const Scalar wb(b.AngularVelocity());
+
+       const Vector vap(a.VelocityAt(na.Origin()));
+       const Vector vbp(b.VelocityAt(na.Origin()));
+       const Vector vab = vap - vbp;
+
+       const Vector rap90((na.Origin() - a.Origin()).Rotate90());
+       const Vector rbp90((na.Origin() - b.Origin()).Rotate90());
+
+       const Scalar ia(a.Mass());
+       const Scalar ib(b.Mass());
+
+       const Scalar rap90dotN(rap90.Dot(na.Direction()));
+       const Scalar rbp90dotN(rbp90.Dot(na.Direction()));
+
+       const Scalar j(
+                       (((-(1 + e)) * vab).Dot(na.Direction()))
+                       / (na.Direction().Dot(na.Direction() * ((1.0 / a.Mass()) + (1.0 / b.Mass())))
+                                       + ((rap90dotN * rap90dotN) / ia)
+                                       + ((rbp90dotN * rbp90dotN) / ib) ));
+
+       const Vector va2(va + ((j / a.Mass()) * na.Direction()));
+       const Vector vb2(vb - ((j / b.Mass()) * na.Direction()));
+       const Scalar wa2(wa + ((rap90.Dot(j * na.Direction())) / ia));
+       const Scalar wb2(wb - ((rbp90.Dot(j * na.Direction())) / ib));
+
+       a.linearVelocity = va2;
+       a.angularVelocity = wa2;
+       b.linearVelocity = vb2;
+       b.angularVelocity = wb2;
+}
+
+void Entity::InfInfCollisionResponse(Entity &a, const Ray &na, Entity &b) {
+       // If both elements are standing still or both are moving, move them away
+       // from each other. Otherwise, move the moving one.
+       if ((a.linearVelocity == Vector() && b.linearVelocity == Vector())
+                       || (a.linearVelocity != Vector() && b.linearVelocity != Vector())) {
+               a.Translate(na.Direction());
+               b.Translate(-na.Direction());
+               Ray n;
+               while (a.shape->CheckCollision(*b.shape, n)) {
+                       a.Translate(n.Direction());
+                       b.Translate(-n.Direction());
+               }
+       } else if (a.linearVelocity == Vector()) {
+               b.Translate(-na.Direction());
+               Ray n;
+               while (b.shape->CheckCollision(*a.shape, n)) {
+                       b.Translate(n.Direction());
+               }
+       } else {
+               a.Translate(na.Direction());
+               Ray n;
+               while (a.shape->CheckCollision(*b.shape, n)) {
+                       a.Translate(n.Direction());
+               }
+       }
+}
+
+}