}
-void World::Update(int delta) {
- for (int i = 0; i < delta; ++i) {
- const float dt = 1e-3;
- for (Entity &e : entities) {
- e.Update(dt, gravity, terminal);
-
- const AABB &b = e.Bounds();
-
- // world bounds collision
- if (b.Top() < 0) e.Move(Vector<float>(0, -b.Top()));
- if (b.Right() > size.x) e.Move(Vector<float>(size.x - b.Right(), 0));
- if (b.Bottom() > size.y) e.Move(Vector<float>(0, size.y - b.Bottom()));
- if (b.Left() < 0) e.Move(Vector<float>(-b.Left(), 0));
-
- const Vector<int> cBegin(b.Left(), b.Top());
- const Vector<int> cEnd(b.Right(), b.Bottom());
-
- Vector<float> topResponse;
- for (Vector<int> pos(cBegin); pos.x < cEnd.x; ++pos.x) {
- if (TileAt(pos).IsSolid()) {
- topResponse = Vector<float>(0, pos.y + 1 - b.Top());
- break;
- }
- }
- Vector<float> bottomResponse;
- for (Vector<int> pos(cBegin.x, cEnd.y); pos.x < cEnd.x; ++pos.x) {
- if (TileAt(pos).IsSolid()) {
- bottomResponse = Vector<float>(0, pos.y - b.Bottom());
- break;
- }
- }
- if (!IsZero(topResponse)) {
- if (IsZero(bottomResponse)) {
- e.Move(topResponse);
+void World::Update(float dt) {
+ for (Entity &e : entities) {
+ e.Update(dt, gravity, terminal);
+ e.onGround = false;
+
+ const AABB &b = e.bounds;
+
+ // world bounds collision
+ if (b.Top() < 0) {
+ e.Move(Vector<float>(0, -b.Top()));
+ e.vel.y = 0;
+ }
+ if (b.Right() > size.x) {
+ e.Move(Vector<float>(size.x - b.Right(), 0));
+ e.vel.x = 0;
+ }
+ if (b.Bottom() > size.y) {
+ e.Move(Vector<float>(0, size.y - b.Bottom()));
+ e.vel.y = 0;
+ e.onGround = true;
+ }
+ if (b.Left() < 0) {
+ e.Move(Vector<float>(-b.Left(), 0));
+ e.vel.x = 0;
+ }
+
+ const Vector<int> cBegin(b.Left(), b.Top());
+ const Vector<int> cEnd(b.Right() + 1, b.Bottom() + 1);
+
+ Vector<float> min;
+ Vector<float> max;
+
+ for (Vector<int> pos(cBegin); pos.y < cEnd.y; ++pos.y) {
+ for (pos.x = cBegin.x; pos.x < cEnd.x; ++pos.x) {
+ if (!TileAt(pos).IsSolid()) continue;
+ const AABB tBounds(pos, Vector<float>(1, 1));
+ Vector<float> pos;
+ Vector<float> norm;
+ Vector<float> depth;
+ if (!e.bounds.Intersects(tBounds, pos, norm, depth)) {
+ continue;
}
- } else if (!IsZero(bottomResponse)) {
- e.Move(bottomResponse);
+ if (depth.x < min.x) min.x = depth.x;
+ if (depth.x > max.x) max.x = depth.x;
+ if (depth.y < min.y) min.y = depth.y;
+ if (depth.y > max.y) max.y = depth.y;
}
+ }
- Vector<float> leftResponse;
- for (Vector<int> pos(cBegin); pos.y < cEnd.y; ++pos.y) {
- if (TileAt(pos).IsSolid()) {
- leftResponse = Vector<float>(pos.x + 1 - b.Left(), 0);
- break;
- }
+ Vector<float> resp;
+ if (min.x != 0) {
+ if (max.x == 0) {
+ resp.x = min.x;
}
- Vector<float> rightResponse;
- for (Vector<int> pos(cEnd.x, cBegin.y); pos.y < cEnd.y; ++pos.y) {
- if (TileAt(pos).IsSolid()) {
- rightResponse = Vector<float>(pos.x - b.Right(), 0);
- break;
- }
+ } else {
+ resp.x = max.x;
+ }
+ if (min.y != 0) {
+ if (max.y == 0) {
+ resp.y = min.y;
}
- if (!IsZero(leftResponse)) {
- if (IsZero(rightResponse)) {
- e.Move(leftResponse);
- }
- } else if (!IsZero(rightResponse)) {
- e.Move(rightResponse);
+ } else {
+ resp.y = max.y;
+ }
+ e.Move(resp);
+ if (resp.x != 0) {
+ e.vel.x = 0;
+ }
+ if (resp.y != 0) {
+ e.vel.y = 0;
+ if (resp.y < 0) {
+ e.onGround = true;
}
}
}