X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fworld%2FWorld.cpp;fp=src%2Fworld%2FWorld.cpp;h=c76f8608bb82b30c4aaadda76413658df2fe0999;hb=a8523bee4fc349a800f5f6d67b470c3a801beaa9;hp=7276ece6fdaa5b16519e3e24c0724e16a6b2d7f8;hpb=962405ec344818a7f6850d243feca7989ae5d41b;p=orbi.git diff --git a/src/world/World.cpp b/src/world/World.cpp index 7276ece..c76f860 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -3,6 +3,9 @@ #include "Collision.h" #include "../graphics/const.h" +#include +#include + namespace orbi { @@ -11,6 +14,7 @@ World::World(Vector size) , count(size.x * size.y) , gravity(0, 5) , terminal(50, 50) +, fixSpeed(5) , tiles(count) { } @@ -21,74 +25,105 @@ void World::Update(float dt) { e.Update(dt, gravity, terminal); e.onGround = false; - const AABB &b = e.bounds; + BoundsCollision(e, dt); + TileCollision(e, dt); + + } +} + +void World::BoundsCollision(Entity &e, float dt) { + if (e.vbox.Top() < 0) { + e.Move(Vector(0, -e.vbox.Top())); + e.vel.y = 0; + } + if (e.vbox.Bottom() > size.y) { + e.Move(Vector(0, size.y - e.vbox.Bottom())); + e.vel.y = 0; + e.onGround = true; + } + if (e.hbox.Right() > size.x) { + e.Move(Vector(size.x - e.hbox.Right(), 0)); + e.vel.x = 0; + } + if (e.hbox.Left() < 0) { + e.Move(Vector(-e.hbox.Left(), 0)); + e.vel.x = 0; + } +} + +void World::TileCollision(Entity &e, float dt) { + Vector response; - // world bounds collision - if (b.Top() < 0) { - e.Move(Vector(0, -b.Top())); + // top + for (int x = e.vbox.Left(), y = e.vbox.Top(), + end = std::ceil(e.vbox.Right()); x < end; ++x) { + const Tile &tile = TileAt(Vector(x, y)); + if (tile.IsSolid()) { + response.y = y + 1 - e.vbox.Top(); e.vel.y = 0; + break; } - if (b.Right() > size.x) { - e.Move(Vector(size.x - b.Right(), 0)); - e.vel.x = 0; - } - if (b.Bottom() > size.y) { - e.Move(Vector(0, size.y - b.Bottom())); - e.vel.y = 0; + } + + // bottom + for (int x = e.vbox.Left(), y = e.vbox.Bottom(), + end = std::ceil(e.vbox.Right()); x < end; ++x) { + const Tile &tile = TileAt(Vector(x, y)); + if (tile.IsSolid()) { + response.y = y - e.vbox.Bottom(); e.onGround = true; + e.vel.y = 0; + break; } - if (b.Left() < 0) { - e.Move(Vector(-b.Left(), 0)); - e.vel.x = 0; - } - - const Vector cBegin(b.Left(), b.Top()); - const Vector cEnd(b.Right() + 1, b.Bottom() + 1); - - Vector min; - Vector max; - - for (Vector 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 = TileShapeAt(pos); - Collision coll; - if (!e.bounds.Intersects(tBounds, coll)) { - continue; - } - if (coll.depth.x < min.x) min.x = coll.depth.x; - if (coll.depth.x > max.x) max.x = coll.depth.x; - if (coll.depth.y < min.y) min.y = coll.depth.y; - if (coll.depth.y > max.y) max.y = coll.depth.y; + } + if (response.y <= 0) { + // bottom, second row + // due to the hbox's huge bottom gap + for (int x = e.vbox.Left(), y = e.vbox.Bottom() - 1, + end = std::ceil(e.vbox.Right()); x < end; ++x) { + const Tile &tile = TileAt(Vector(x, y)); + if (tile.IsSolid()) { + response.y = -1; + e.onGround = true; + e.vel.y = 0; + break; } } + } - Vector resp; - if (min.x != 0) { - if (max.x == 0) { - resp.x = min.x; - } - } else { - resp.x = max.x; - } - if (min.y != 0) { - if (max.y == 0) { - resp.y = min.y; - } - } else { - resp.y = max.y; - } - e.Move(resp); - if (resp.x != 0) { + // left + for (int y = e.hbox.Top(), x = e.hbox.Left(), + end = std::ceil(e.hbox.Bottom()); y < end; ++y) { + const Tile &tile = TileAt(Vector(x, y)); + if (tile.IsSolid()) { + response.x = x + 1 - e.hbox.Left(); e.vel.x = 0; + break; } - if (resp.y != 0) { - e.vel.y = 0; - if (resp.y < 0) { - e.onGround = true; - } + } + + // right + for (int y = e.hbox.Top(), x = e.hbox.Right(), + end = std::ceil(e.hbox.Bottom()); y < end; ++y) { + const Tile &tile = TileAt(Vector(x, y)); + if (tile.IsSolid()) { + response.x = x - e.hbox.Right(); + e.vel.x = 0; + break; } } + + if (response.x > fixSpeed * dt) { + response.x = fixSpeed * dt; + } else if (response.x < -fixSpeed * dt) { + response.x = -fixSpeed * dt; + } + if (response.y > fixSpeed * dt) { + response.y = fixSpeed * dt; + } else if (response.y < -fixSpeed * dt) { + response.y = -fixSpeed * dt; + } + e.Move(response); }