X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fworld%2FWorld.cpp;h=a198ccc77a2f06b17ea49c6b4806f392f3d6448a;hb=a73a6dd63407b5f5ef5b0c635551ad27b27c95d6;hp=f4d80f95476beab74a2e32eac354f5f10c062659;hpb=dbc08d84d9de1a77cba0dd97e4701f4ac99d056e;p=orbi.git diff --git a/src/world/World.cpp b/src/world/World.cpp index f4d80f9..a198ccc 100644 --- a/src/world/World.cpp +++ b/src/world/World.cpp @@ -1,7 +1,14 @@ #include "World.h" +#include "Collision.h" +#include "Entity.h" #include "../graphics/const.h" +#include +#include + +using namespace std; + namespace orbi { @@ -10,92 +17,155 @@ World::World(Vector size) , count(size.x * size.y) , gravity(0, 5) , terminal(50, 50) +, fixSpeed(5) , tiles(count) { } void World::Update(float dt) { - for (Entity &e : entities) { - e.Update(dt, gravity, terminal); - e.onGround = false; + 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())); + } +} + +void World::BoundsCollision(Entity &e, float dt) { + if (e.vbox.Top() < 0) { + e.Move(Vector(0, -e.vbox.Top())); + if (e.vel.y < 0) { e.vel.y = 0; } - 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())); + } + if (e.vbox.Bottom() > size.y) { + e.Move(Vector(0, size.y - e.vbox.Bottom())); + if (e.vel.y > 0) { e.vel.y = 0; - e.onGround = true; } - if (b.Left() < 0) { - e.Move(Vector(-b.Left(), 0)); + e.onGround = true; + } + if (e.hbox.Right() > size.x) { + e.Move(Vector(size.x - e.hbox.Right(), 0)); + if (e.vel.x > 0) { e.vel.x = 0; } + } + if (e.hbox.Left() < 0) { + e.Move(Vector(-e.hbox.Left(), 0)); + if (e.vel.x < 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(pos, Vector(1, 1)); - Vector pos; - Vector norm; - Vector depth; - if (!e.bounds.Intersects(tBounds, pos, norm, depth)) { - continue; - } - 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; +void World::TileCollision(Entity &e, float dt) { + Vector response; + + // 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(); + if (e.vel.y < 0) { + e.vel.y = 0; } + break; } + } - Vector resp; - if (min.x != 0) { - if (max.x == 0) { - resp.x = min.x; + // 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; + if (e.vel.y > 0) { + e.vel.y = 0; } - } else { - resp.x = max.x; + break; } - if (min.y != 0) { - if (max.y == 0) { - resp.y = min.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; + if (e.vel.y > 0) { + e.vel.y = 0; + } + break; } - } else { - resp.y = max.y; } - e.Move(resp); - if (resp.x != 0) { - e.vel.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(); + if (e.vel.x < 0) { + 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(); + if (e.vel.x > 0) { + 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); +} -Entity &World::AddEntity(const Entity &e) { - entities.emplace_back(e); - return entities.back(); +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 + } + } + } } + }