| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- #include "mcDungeonsgameplay.h"
- void McDungeonsGameplay::resolveConstrains(PhysicsComponent &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(PhysicsComponent &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 = {150,150};
- 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(PhysicsComponent &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 - size.x/2.f) / BLOCK_SIZE;
- maxX = ceil((pos.x + abs(delta.x) + BLOCK_SIZE + size.x / 2.f) / BLOCK_SIZE);
- minY = (pos.y - abs(delta.y) - BLOCK_SIZE - size.y / 2.f) / BLOCK_SIZE;
- maxY = ceil((pos.y + abs(delta.y) + BLOCK_SIZE + size.y/2.f) / 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;
- }
|