+
+ Vector<float> at;
+ if (WorldCollision(e, at)) {
+ float speed = Length(e.vel);
+ Vector<float> normVel = e.vel / speed;
+ float steps = 0;
+ while (MassAt(e.pos) > 0) {
+ e.pos -= normVel;
+ steps += 1.0f;
+ }
+ const Vector<float> normal = NormalAt(e.pos + normVel);
+ e.vel = Reflect(e.vel, normal);
+ speed = Length(e.vel);
+ normVel = e.vel / speed;
+ // some kind of friction, depends on angle to normal
+ speed *= (fricDyn * (std::abs(Dot(normVel, normal))));
+ if (speed > fricStat) {
+ speed -= fricStat;
+ e.vel = normVel * speed;
+ e.pos += normVel * steps;
+ } else {
+ e.vel = Vector<float>(0, 0);
+ }
+ }
+ }
+}
+
+
+bool World::WorldCollision(const Entity &e, Vector<float> &at) const {
+ if (InBounds(e.pos) && MassAt(e.pos) > 0) {
+ at = e.pos;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+Vector<float> World::NormalAt(Vector<float> pos) const {
+ constexpr Vector<float> check[] = {
+ { 0, -2 },
+ { 0.765367, -1.84776 },
+ { 1.41421, -1.41421 },
+ { 1.84776, -0.765367 },
+ { 2, 0 },
+ { 1.84776, 0.765367 },
+ { 1.41421, 1.41421 },
+ { 0.765367, 1.84776 },
+ { 0, 2 },
+ { -0.765367, 1.84776 },
+ { -1.41421, 1.41421 },
+ { -1.84776, 0.765367 },
+ { -2, 0 },
+ { -1.84776, -0.765367 },
+ { -1.41421, -1.41421 },
+ { -0.765367, -1.84776 },
+ };
+ Vector<float> normal;
+ for (auto v : check) {
+ if (MassAt(pos + v) == 0) {
+ normal += v;
+ }