|
|
@@ -0,0 +1,206 @@
|
|
|
+
|
|
|
+
|
|
|
+#include "mcDungeonsgameplay.h"
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void McDungeonsGameplay::resolveConstrains(Player &player)
|
|
|
+{
|
|
|
+ glm::ivec2 mapSize = {150,150};
|
|
|
+
|
|
|
+ bool upTouch = 0;
|
|
|
+ bool downTouch = 0;
|
|
|
+ bool leftTouch = 0;
|
|
|
+ bool rightTouch = 0;
|
|
|
+
|
|
|
+ glm::vec2 &pos = player.position;
|
|
|
+
|
|
|
+ float distance = glm::length(player.lastPos - pos);
|
|
|
+ const float BLOCK_SIZE = 1.f;
|
|
|
+
|
|
|
+ if (distance < BLOCK_SIZE)
|
|
|
+ {
|
|
|
+ checkCollisionBrute(player,
|
|
|
+ pos,
|
|
|
+ player.lastPos,
|
|
|
+ upTouch,
|
|
|
+ downTouch,
|
|
|
+ leftTouch,
|
|
|
+ rightTouch
|
|
|
+ );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ glm::vec2 newPos = player.lastPos;
|
|
|
+ glm::vec2 delta = pos - player.lastPos;
|
|
|
+ delta = glm::normalize(delta);
|
|
|
+ delta *= 0.9 * BLOCK_SIZE;
|
|
|
+
|
|
|
+ do
|
|
|
+ {
|
|
|
+ newPos += delta;
|
|
|
+ glm::vec2 posTest = newPos;
|
|
|
+ checkCollisionBrute(player,
|
|
|
+ newPos,
|
|
|
+ player.lastPos,
|
|
|
+ upTouch,
|
|
|
+ downTouch,
|
|
|
+ leftTouch,
|
|
|
+ rightTouch);
|
|
|
+
|
|
|
+ if (newPos != posTest)
|
|
|
+ {
|
|
|
+ pos = newPos;
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ } while (glm::length((newPos + delta) - pos) > 1.0f * BLOCK_SIZE);
|
|
|
+
|
|
|
+ checkCollisionBrute(player,
|
|
|
+ pos,
|
|
|
+ player.lastPos,
|
|
|
+ upTouch,
|
|
|
+ downTouch,
|
|
|
+ leftTouch,
|
|
|
+ rightTouch);
|
|
|
+ }
|
|
|
+
|
|
|
+end:
|
|
|
+
|
|
|
+ //clamp the box if needed
|
|
|
+ //if (pos.x < 0) { pos.x = 0; leftTouch = true; }
|
|
|
+ //if (pos.x + player.size.x > (mapSize.x) * BLOCK_SIZE)
|
|
|
+ //{
|
|
|
+ // pos.x = ((mapSize.x) * BLOCK_SIZE) - player.size.x; rightTouch = true;
|
|
|
+ //}
|
|
|
+
|
|
|
+ return;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+void McDungeonsGameplay::checkCollisionBrute(Player &player, glm::vec2 &pos, glm::vec2 lastPos
|
|
|
+ , bool &upTouch, bool &downTouch, bool &leftTouch, bool &rightTouch)
|
|
|
+{
|
|
|
+ glm::vec2 delta = pos - lastPos;
|
|
|
+ const float BLOCK_SIZE = 1.f;
|
|
|
+
|
|
|
+ glm::vec2 &dimensions = player.size;
|
|
|
+
|
|
|
+ glm::ivec2 mapSize = {100,100};
|
|
|
+
|
|
|
+ if (
|
|
|
+ (pos.y < -dimensions.y)
|
|
|
+ || (pos.x < -dimensions.x)
|
|
|
+ || (pos.y > mapSize.x * BLOCK_SIZE)
|
|
|
+ || (pos.x > mapSize.y * BLOCK_SIZE)
|
|
|
+ )
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ glm::vec2 newPos = performCollision(player, {pos.x, lastPos.y}, {dimensions.x, dimensions.y}, {delta.x, 0},
|
|
|
+ upTouch, downTouch, leftTouch, rightTouch);
|
|
|
+ pos = performCollision(player, {newPos.x, pos.y}, {dimensions.x, dimensions.y}, {0, delta.y},
|
|
|
+ upTouch, downTouch, leftTouch, rightTouch);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+const int playerPosY = 13;
|
|
|
+glm::vec2 McDungeonsGameplay::performCollision(Player &player, glm::vec2 pos, glm::vec2 size,
|
|
|
+ glm::vec2 delta, bool &upTouch, bool &downTouch, bool &leftTouch, bool &rightTouch)
|
|
|
+{
|
|
|
+
|
|
|
+
|
|
|
+ auto aabb = [](glm::vec4 b1, glm::vec4 b2, float delta)
|
|
|
+ {
|
|
|
+ b2.x += delta;
|
|
|
+ b2.y += delta;
|
|
|
+ b2.z -= delta * 2;
|
|
|
+ b2.w -= delta * 2;
|
|
|
+
|
|
|
+ if (((b1.x - b2.x < b2.z)
|
|
|
+ && b2.x - b1.x < b1.z
|
|
|
+ )
|
|
|
+ && ((b1.y - b2.y < b2.w)
|
|
|
+ && b2.y - b1.y < b1.w
|
|
|
+ )
|
|
|
+ )
|
|
|
+ {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ glm::ivec2 mapSize = {150,150};
|
|
|
+
|
|
|
+ int minX = 0;
|
|
|
+ int minY = 0;
|
|
|
+ int maxX = mapSize.x;
|
|
|
+ int maxY = mapSize.y;
|
|
|
+
|
|
|
+ auto &dimensions = player.size;
|
|
|
+
|
|
|
+ const float BLOCK_SIZE = 1.f;
|
|
|
+
|
|
|
+ minX = (pos.x - abs(delta.x) - BLOCK_SIZE) / BLOCK_SIZE;
|
|
|
+ maxX = ceil((pos.x + abs(delta.x) + BLOCK_SIZE + size.x) / BLOCK_SIZE);
|
|
|
+
|
|
|
+ minY = (pos.y - abs(delta.y) - BLOCK_SIZE) / BLOCK_SIZE;
|
|
|
+ maxY = ceil((pos.y + abs(delta.y) + BLOCK_SIZE + size.y) / BLOCK_SIZE);
|
|
|
+
|
|
|
+ minX = std::max(0, minX);
|
|
|
+ minY = std::max(0, minY);
|
|
|
+ maxX = std::min(mapSize.x, maxX);
|
|
|
+ maxY = std::min(mapSize.y, maxY);
|
|
|
+
|
|
|
+ for (int y = minY; y < maxY; y++)
|
|
|
+ for (int x = minX; x < maxX; x++)
|
|
|
+ {
|
|
|
+ if (
|
|
|
+ getBlockUnsafe(x, playerPosY, y) != 0 ||
|
|
|
+ getBlockUnsafe(x, playerPosY + 1, y) != 0 ||
|
|
|
+ getBlockUnsafe(x, playerPosY-1, y) ==0
|
|
|
+ )
|
|
|
+ {
|
|
|
+ if (aabb({pos - dimensions / 2.f,dimensions}, {x * BLOCK_SIZE - BLOCK_SIZE / 2.f, y * BLOCK_SIZE - BLOCK_SIZE / 2.f, BLOCK_SIZE, BLOCK_SIZE}, 0.0001f))
|
|
|
+ {
|
|
|
+ if (delta.x != 0)
|
|
|
+ {
|
|
|
+ if (delta.x < 0) // moving left
|
|
|
+ {
|
|
|
+ leftTouch = 1;
|
|
|
+ pos.x = x * BLOCK_SIZE + BLOCK_SIZE/2.f + dimensions.x/2.f;
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ rightTouch = 1;
|
|
|
+ pos.x = x * BLOCK_SIZE - BLOCK_SIZE / 2.f - dimensions.x / 2.f;
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (delta.y != 0)
|
|
|
+ {
|
|
|
+ if (delta.y < 0) //moving up
|
|
|
+ {
|
|
|
+ upTouch = 1;
|
|
|
+ pos.y = y * BLOCK_SIZE + BLOCK_SIZE / 2.f + dimensions.y / 2.f;
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ downTouch = 1;
|
|
|
+ pos.y = y * BLOCK_SIZE - BLOCK_SIZE / 2.f - dimensions.y/2.f;
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+end:
|
|
|
+ return pos;
|
|
|
+}
|