|
@@ -116,11 +116,275 @@ bool Entity::tick(double time)
|
|
|
speed.x = norm.x * maxMovementSpeed;
|
|
|
speed.y = norm.y * maxMovementSpeed;
|
|
|
}
|
|
|
- // TODO: collision check
|
|
|
- pos += speed * (float)time;
|
|
|
+ // collision checking
|
|
|
+ Vec3<float> minP = model->getMinPos();
|
|
|
+ Vec3<float> maxP = model->getMaxPos();
|
|
|
+ Vec3<float> worldBoundingBox[8];
|
|
|
+ worldBoundingBox[0] = applyWorldTransformation(minP);
|
|
|
+ worldBoundingBox[1] = applyWorldTransformation({ minP.x, minP.y, maxP.z });
|
|
|
+ worldBoundingBox[2] = applyWorldTransformation({ minP.x, maxP.y, minP.z });
|
|
|
+ worldBoundingBox[3] = applyWorldTransformation({ maxP.x, minP.y, minP.z });
|
|
|
+ worldBoundingBox[4] = applyWorldTransformation({ maxP.x, minP.y, maxP.z });
|
|
|
+ worldBoundingBox[5] = applyWorldTransformation({ maxP.x, maxP.y, minP.z });
|
|
|
+ worldBoundingBox[6] = applyWorldTransformation({ minP.x, maxP.y, maxP.z });
|
|
|
+ worldBoundingBox[7] = applyWorldTransformation(maxP);
|
|
|
+ Vec3<float> worldBoundingBoxFloor[8];
|
|
|
+ for (int i = 0; i < 8; i++)
|
|
|
+ {
|
|
|
+ worldBoundingBoxFloor[i] = Vec3<float>(floor(worldBoundingBox[i].x), floor(worldBoundingBox[i].y), floor(worldBoundingBox[i].z));
|
|
|
+ }
|
|
|
+ Vec3<float> frameSpeed = speed * (float)time;
|
|
|
+ bool hasCollided = 0;
|
|
|
+ while (true)
|
|
|
+ {
|
|
|
+ float tf = 1.f;
|
|
|
+ int collType = 0;
|
|
|
+ int updateType = 0;
|
|
|
+ int updateI = 0;
|
|
|
+ if (frameSpeed.x > 0)
|
|
|
+ {
|
|
|
+ for (int i = 0; i < 8; i++)
|
|
|
+ {
|
|
|
+ if (abs(frameSpeed.x) >= abs(worldBoundingBoxFloor[i].x + 1.f - worldBoundingBox[i].x))
|
|
|
+ {
|
|
|
+ float xt = (worldBoundingBoxFloor[i].x + 1.f - worldBoundingBox[i].x) / frameSpeed.x;
|
|
|
+ Vec3<float> tmp = worldBoundingBox[i] + frameSpeed * xt;
|
|
|
+ if (tmp.y >= worldBoundingBoxFloor[i].y && tmp.y < worldBoundingBoxFloor[i].y + 1.f && tmp.z >= worldBoundingBoxFloor[i].z && tmp.z < worldBoundingBoxFloor[i].z + 1.f)
|
|
|
+ {
|
|
|
+ Block* b = currentGame->zBlockAt(Vec3<int>{ (int)worldBoundingBoxFloor[i].x + 1, (int)worldBoundingBoxFloor[i].y, (int)worldBoundingBoxFloor[i].z });
|
|
|
+ if (b) // TODO: ignore passable blocks
|
|
|
+ {
|
|
|
+ if (xt < tf)
|
|
|
+ {
|
|
|
+ tf = xt;
|
|
|
+ collType = 1;
|
|
|
+ updateType = 0;
|
|
|
+ }
|
|
|
+ hasCollided = 1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (xt < tf)
|
|
|
+ {
|
|
|
+ tf = xt;
|
|
|
+ collType = 0;
|
|
|
+ updateType = 1;
|
|
|
+ updateI = i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (frameSpeed.x < 0)
|
|
|
+ {
|
|
|
+ for (int i = 0; i < 8; i++)
|
|
|
+ {
|
|
|
+ if (abs(frameSpeed.x) >= abs(worldBoundingBoxFloor[i].x - worldBoundingBox[i].x))
|
|
|
+ {
|
|
|
+ float xt = (worldBoundingBoxFloor[i].x - worldBoundingBox[i].x) / frameSpeed.x;
|
|
|
+ Vec3<float> tmp = worldBoundingBox[i] + frameSpeed * xt;
|
|
|
+ if (tmp.y >= worldBoundingBoxFloor[i].y && tmp.y < worldBoundingBoxFloor[i].y + 1.f && tmp.z >= worldBoundingBoxFloor[i].z && tmp.z < worldBoundingBoxFloor[i].z + 1.f)
|
|
|
+ {
|
|
|
+ Block* b = currentGame->zBlockAt(Vec3<int>{ (int)worldBoundingBoxFloor[i].x - 1, (int)worldBoundingBoxFloor[i].y, (int)worldBoundingBoxFloor[i].z });
|
|
|
+ if (b) // TODO: ignore passable blocks
|
|
|
+ {
|
|
|
+ if (xt < tf)
|
|
|
+ {
|
|
|
+ tf = xt;
|
|
|
+ collType = 1;
|
|
|
+ updateType = 0;
|
|
|
+ }
|
|
|
+ hasCollided = 1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (xt < tf)
|
|
|
+ {
|
|
|
+ tf = xt;
|
|
|
+ collType = 0;
|
|
|
+ updateType = 1;
|
|
|
+ updateI = i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (frameSpeed.y > 0)
|
|
|
+ {
|
|
|
+ for (int i = 0; i < 8; i++)
|
|
|
+ {
|
|
|
+ if (abs(frameSpeed.y) >= abs(worldBoundingBoxFloor[i].y + 1.f - worldBoundingBox[i].y))
|
|
|
+ {
|
|
|
+ float yt = (worldBoundingBoxFloor[i].y + 1.f - worldBoundingBox[i].y) / frameSpeed.y;
|
|
|
+ Vec3<float> tmp = worldBoundingBox[i] + frameSpeed * yt;
|
|
|
+ if (tmp.x >= worldBoundingBoxFloor[i].x && tmp.x < worldBoundingBoxFloor[i].x + 1.f && tmp.z >= worldBoundingBoxFloor[i].z && tmp.z < worldBoundingBoxFloor[i].z + 1.f)
|
|
|
+ {
|
|
|
+ Block* b = currentGame->zBlockAt(Vec3<int>{ (int)worldBoundingBoxFloor[i].x, (int)worldBoundingBoxFloor[i].y + 1, (int)worldBoundingBoxFloor[i].z });
|
|
|
+ if (b) // TODO: ignore passable blocks
|
|
|
+ {
|
|
|
+ if (yt < tf)
|
|
|
+ {
|
|
|
+ tf = yt;
|
|
|
+ collType = 2;
|
|
|
+ updateType = 0;
|
|
|
+ }
|
|
|
+ hasCollided = 1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (yt < tf)
|
|
|
+ {
|
|
|
+ tf = yt;
|
|
|
+ collType = 0;
|
|
|
+ updateType = 2;
|
|
|
+ updateI = i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (frameSpeed.y < 0)
|
|
|
+ {
|
|
|
+ for (int i = 0; i < 8; i++)
|
|
|
+ {
|
|
|
+ if (abs(frameSpeed.y) >= abs(worldBoundingBoxFloor[i].y - worldBoundingBox[i].y))
|
|
|
+ {
|
|
|
+ float yt = (worldBoundingBoxFloor[i].y - worldBoundingBox[i].y) / frameSpeed.y;
|
|
|
+ Vec3<float> tmp = worldBoundingBox[i] + frameSpeed * yt;
|
|
|
+ if (tmp.x >= worldBoundingBoxFloor[i].x && tmp.x < worldBoundingBoxFloor[i].x + 1.f && tmp.z >= worldBoundingBoxFloor[i].z && tmp.z < worldBoundingBoxFloor[i].z + 1.f)
|
|
|
+ {
|
|
|
+ Block* b = currentGame->zBlockAt(Vec3<int>{ (int)worldBoundingBoxFloor[i].x, (int)worldBoundingBoxFloor[i].y - 1, (int)worldBoundingBoxFloor[i].z });
|
|
|
+ if (b) // TODO: ignore passable blocks
|
|
|
+ {
|
|
|
+ if (yt < tf)
|
|
|
+ {
|
|
|
+ tf = yt;
|
|
|
+ collType = 2;
|
|
|
+ updateType = 0;
|
|
|
+ }
|
|
|
+ hasCollided = 1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (yt < tf)
|
|
|
+ {
|
|
|
+ tf = yt;
|
|
|
+ collType = 0;
|
|
|
+ updateType = 2;
|
|
|
+ updateI = i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (frameSpeed.z > 0)
|
|
|
+ {
|
|
|
+ for (int i = 0; i < 8; i++)
|
|
|
+ {
|
|
|
+ if (abs(frameSpeed.z) >= abs(worldBoundingBoxFloor[i].z + 1.f - worldBoundingBox[i].z))
|
|
|
+ {
|
|
|
+ float zt = (worldBoundingBoxFloor[i].z + 1.f - worldBoundingBox[i].z) / frameSpeed.z;
|
|
|
+ Vec3<float> tmp = worldBoundingBox[i] + frameSpeed * zt;
|
|
|
+ if (zt <= 1.f && tmp.x >= worldBoundingBoxFloor[i].x && tmp.x < worldBoundingBoxFloor[i].x + 1.f && tmp.y >= worldBoundingBoxFloor[i].y && tmp.y < worldBoundingBoxFloor[i].y + 1.f)
|
|
|
+ {
|
|
|
+ Block* b = currentGame->zBlockAt(Vec3<int>{ (int)worldBoundingBoxFloor[i].x, (int)worldBoundingBoxFloor[i].y, (int)worldBoundingBoxFloor[i].z + 1 });
|
|
|
+ if (b) // TODO: ignore passable blocks
|
|
|
+ {
|
|
|
+ if (zt < tf)
|
|
|
+ {
|
|
|
+ tf = zt;
|
|
|
+ collType = 3;
|
|
|
+ }
|
|
|
+ hasCollided = 1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (zt < tf)
|
|
|
+ {
|
|
|
+ tf = zt;
|
|
|
+ collType = 0;
|
|
|
+ updateType = 3;
|
|
|
+ updateI = i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (frameSpeed.z < 0)
|
|
|
+ {
|
|
|
+ for (int i = 0; i < 8; i++)
|
|
|
+ {
|
|
|
+ if (abs(frameSpeed.z) >= abs(worldBoundingBoxFloor[i].z - worldBoundingBox[i].z))
|
|
|
+ {
|
|
|
+ float zt = (worldBoundingBoxFloor[i].z - worldBoundingBox[i].z) / frameSpeed.z;
|
|
|
+ Vec3<float> tmp = worldBoundingBox[i] + frameSpeed * zt;
|
|
|
+ if (tmp.x >= worldBoundingBoxFloor[i].x && tmp.x < worldBoundingBoxFloor[i].x + 1.f && tmp.y >= worldBoundingBoxFloor[i].y && tmp.y < worldBoundingBoxFloor[i].y + 1)
|
|
|
+ {
|
|
|
+ Block* b = currentGame->zBlockAt(Vec3<int>{ (int)worldBoundingBoxFloor[i].x, (int)worldBoundingBoxFloor[i].y, (int)worldBoundingBoxFloor[i].z - 1 });
|
|
|
+ if (b) // TODO: ignore passable blocks
|
|
|
+ {
|
|
|
+ if (zt < tf)
|
|
|
+ {
|
|
|
+ tf = zt;
|
|
|
+ collType = 3;
|
|
|
+ updateType = 0;
|
|
|
+ }
|
|
|
+ hasCollided = 1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (zt < tf)
|
|
|
+ {
|
|
|
+ tf = zt;
|
|
|
+ collType = 0;
|
|
|
+ updateType = 3;
|
|
|
+ updateI = i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (collType == 1)
|
|
|
+ frameSpeed.x = tf > 0.1f ? frameSpeed.x * (tf - 0.1f) : 0.f;
|
|
|
+ if (collType == 2)
|
|
|
+ frameSpeed.y = tf > 0.1f ? frameSpeed.y * (tf - 0.1f) : 0.f;
|
|
|
+ if (collType == 3)
|
|
|
+ frameSpeed.z = tf > 0.1f ? frameSpeed.z * (tf - 0.1f) : 0.f;
|
|
|
+ if (updateType == 1)
|
|
|
+ {
|
|
|
+ if ((int)worldBoundingBoxFloor[updateI].x < (int)floor(worldBoundingBox[updateI].x + frameSpeed.x))
|
|
|
+ worldBoundingBoxFloor[updateI].x++;
|
|
|
+ if ((int)worldBoundingBoxFloor[updateI].x > (int)floor(worldBoundingBox[updateI].x + frameSpeed.x))
|
|
|
+ worldBoundingBoxFloor[updateI].x--;
|
|
|
+ }
|
|
|
+ if (updateType == 2)
|
|
|
+ {
|
|
|
+ if ((int)worldBoundingBoxFloor[updateI].y < (int)floor(worldBoundingBox[updateI].y + frameSpeed.y))
|
|
|
+ worldBoundingBoxFloor[updateI].y++;
|
|
|
+ if ((int)worldBoundingBoxFloor[updateI].y > (int)floor(worldBoundingBox[updateI].y + frameSpeed.y))
|
|
|
+ worldBoundingBoxFloor[updateI].y--;
|
|
|
+ }
|
|
|
+ if (updateType == 3)
|
|
|
+ {
|
|
|
+ if ((int)worldBoundingBoxFloor[updateI].z < (int)floor(worldBoundingBox[updateI].z + frameSpeed.z))
|
|
|
+ worldBoundingBoxFloor[updateI].z++;
|
|
|
+ if ((int)worldBoundingBoxFloor[updateI].z > (int)floor(worldBoundingBox[updateI].z + frameSpeed.z))
|
|
|
+ worldBoundingBoxFloor[updateI].z--;
|
|
|
+ }
|
|
|
+ if (updateType || collType)
|
|
|
+ continue;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ pos += frameSpeed;
|
|
|
currentGame->zKamera()->setPosition(pos + Vec3<float>(0.f, 0.f, 1.5f));
|
|
|
((Game*)(Menu*)menuRegister->get("game"))->updatePosition(pos, 0, { 0, 0, 0 });
|
|
|
- if (flags != lastFlags || direction != lastDirection || timeSinceSync >= 1)
|
|
|
+ if (flags != lastFlags || direction != lastDirection || timeSinceSync >= 1 || hasCollided)
|
|
|
{
|
|
|
if (timeSinceSync > 0)
|
|
|
{
|