X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fworld%2FWorld.cpp;h=088712acae45ac2720322954a7f68eac3216fc25;hb=7cf057b5b3a28c3896af27cb725fbf0b4f1459c2;hp=e390914fae7eb34adccc08de26649c697fe15165;hpb=4a51a83bdff30d1e25a5867cfb19936adc0034b1;p=orbi.git diff --git a/src/world/World.cpp b/src/world/World.cpp index e390914..088712a 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -1,7 +1,13 @@ #include "World.h" +#include "Collision.h" #include "../graphics/const.h" +#include +#include + +using namespace std; + namespace orbi { @@ -10,70 +16,133 @@ World::World(Vector size) , count(size.x * size.y) , gravity(0, 5) , terminal(50, 50) +, fixSpeed(5) , tiles(count) { } -void World::Update(int delta) { - for (int i = 0; i < delta; ++i) { - const float dt = 1e-3; - for (Entity &e : entities) { +void World::Update(float dt) { + for (Entity &e : entities) { + if (e.onGround) { + e.Update(dt, Vector(), terminal); + e.onGround = false; + } else { e.Update(dt, gravity, terminal); + } - const AABB &b = e.Bounds(); + BoundsCollision(e, dt); + TileCollision(e, dt); - // world bounds collision - if (b.Top() < 0) e.Move(Vector(0, -b.Top())); - if (b.Right() > size.x) e.Move(Vector(size.x - b.Right(), 0)); - if (b.Bottom() > size.y) e.Move(Vector(0, size.y - b.Bottom())); - if (b.Left() < 0) e.Move(Vector(-b.Left(), 0)); + } +} - const Vector cBegin(b.Left(), b.Top()); - const Vector cEnd(b.Right(), b.Bottom()); +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; + } +} - Vector topResponse; - for (Vector pos(cBegin); pos.x < cEnd.x; ++pos.x) { - if (TileAt(pos).IsSolid()) { - topResponse = Vector(0, pos.y + 1 - b.Top()); - break; - } - } - Vector bottomResponse; - for (Vector pos(cBegin.x, cEnd.y); pos.x < cEnd.x; ++pos.x) { - if (TileAt(pos).IsSolid()) { - bottomResponse = Vector(0, pos.y - b.Bottom()); - break; - } - } - if (!IsZero(topResponse)) { - if (IsZero(bottomResponse)) { - e.Move(topResponse); - } - } else if (!IsZero(bottomResponse)) { - e.Move(bottomResponse); - } +void World::TileCollision(Entity &e, float dt) { + Vector response; - Vector leftResponse; - for (Vector pos(cBegin); pos.y < cEnd.y; ++pos.y) { - if (TileAt(pos).IsSolid()) { - leftResponse = Vector(pos.x + 1 - b.Left(), 0); - break; - } - } - Vector rightResponse; - for (Vector pos(cEnd.x, cBegin.y); pos.y < cEnd.y; ++pos.y) { - if (TileAt(pos).IsSolid()) { - rightResponse = Vector(pos.x - b.Right(), 0); - break; - } + // 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; + } + } + + // 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 (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; } - if (!IsZero(leftResponse)) { - if (IsZero(rightResponse)) { - e.Move(leftResponse); - } - } else if (!IsZero(rightResponse)) { - e.Move(rightResponse); + } + } + + // 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; + } + } + + // 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); +} + +void World::EntityCollision() { + if (entities.size() <= 1) return; + + auto firstEnd(entities.end()); + --firstEnd; + for (auto first(entities.begin()); first != firstEnd; ++first) { + auto second(first); + ++second; + for (auto secondEnd(entities.end()); second != secondEnd; ++second) { + if (first->bounds.Intersects(second->bounds)) { + // damage + knockback } } }