float CCollision::SweepAABB(CBox box1, CBox box2, CDirection &normalX, CDirection &normalY, float frameTime) { float xInvEntry, yInvEntry; float xInvExit, yInvExit; if (box1.Velocity.x > 0.0f) { xInvEntry = box2.Position.x - (box1.Position.x + box1.Size.x); xInvExit = (box2.Position.x + box2.Size.x) - box1.Position.x; } else { xInvEntry = (box2.Position.x + box2.Size.x) - box1.Position.x; xInvExit = box2.Position.x - (box1.Position.x + box1.Size.x); } if (box1.Velocity.y > 0.0f) { yInvEntry = (box2.Position.y - box2.Size.y) - box1.Position.y; yInvExit = box2.Position.y - (box1.Position.y - box1.Size.y); } else { yInvEntry = box2.Position.y - (box1.Position.y - box1.Size.y); yInvExit = (box2.Position.y - box2.Size.y) - box1.Position.y; } float xEntry, xExit; float yEntry, yExit; if (box1.Velocity.x == 0.0f) { xEntry = -std::numeric_limits<float>::infinity(); xExit = std::numeric_limits<float>::infinity(); } else { xEntry = xInvEntry / box1.Velocity.x; xExit = xInvExit / box1.Velocity.x; } if (box1.Velocity.y == 0.0f) { yEntry = -std::numeric_limits<float>::infinity(); yExit = std::numeric_limits<float>::infinity(); } else { yEntry = yInvEntry / box1.Velocity.y; yExit = yInvExit / box1.Velocity.y; } float entryTime, exitTime; entryTime = __max(xEntry, yEntry); exitTime = __min(xExit, yExit); #pragma region Xét va chạm với các trường hợp còn lại if (entryTime > exitTime || xEntry<0.0f&&yEntry<0.0f || xEntry>frameTime || yEntry>frameTime) { normalX = CDirection::NONE_DIRECT; normalY = CDirection::NONE_DIRECT; if (box1.IsIntersectedWith(box2)) { if (fabsf(box1.Position.y - box1.Size.y - box2.Position.y) <= 2.0f && !(box1.Position.x + box1.Size.x <= box2.Position.x || box1.Position.x >= box2.Position.x + box2.Size.x)) normalY = CDirection::ON_DOWN; else if (fabsf(box1.Position.y - (box2.Position.y - box2.Size.y)) <= 2.0f && !(box1.Position.x + box1.Size.x <= box2.Position.x || box1.Position.x >= box2.Position.x + box2.Size.x)) normalY = CDirection::ON_UP; else if (fabsf(box1.Position.x + box1.Size.x - box2.Position.x) <= 2.0f && !(box1.Position.y - box1.Size.y >= box2.Position.y || box1.Position.y <= box2.Position.y - box2.Size.y)) normalX = CDirection::ON_RIGHT; else if (fabsf(box1.Position.x - (box2.Position.x + box2.Size.x)) <= 2.0f && !(box1.Position.y - box1.Size.y >= box2.Position.y || box1.Position.y <= box2.Position.y - box2.Size.y)) normalX = CDirection::ON_LEFT; else if (!(box1.Position.y - box1.Size.y >= box2.Position.y || box1.Position.y <= box2.Position.y - box2.Size.y || box1.Position.x + box1.Size.x <= box2.Position.x || box1.Position.x >= box2.Position.x + box2.Size.x)) normalX = normalY = CDirection::INSIDE; } return 0; } #pragma endregion #pragma region Nếu có va chạm xảy ra else { if (xEntry > yEntry) { if (box1.Velocity.x > 0.0f) { if (!(box1.Position.y - box1.Size.y >= box2.Position.y || box1.Position.y <= box2.Position.y - box2.Size.y)) { normalX = CDirection::ON_RIGHT; normalY = CDirection::NONE_DIRECT; } else { if (fabsf(box1.Position.y - box1.Size.y - box2.Position.y) <= 2.0f) { normalX = CDirection::NONE_DIRECT; normalY = CDirection::ON_DOWN; entryTime = 0.0f; } else if (fabsf(box1.Position.y - (box2.Position.y - box2.Size.y) <= 2.0f)) { normalX = CDirection::NONE_DIRECT; normalY = CDirection::ON_UP; entryTime = 0.0f; } } } else { if (!(box1.Position.y - box1.Size.y >= box2.Position.y || box1.Position.y <= box2.Position.y - box2.Size.y)) { normalX = CDirection::ON_LEFT; normalY = CDirection::NONE_DIRECT; } else { if (fabsf(box1.Position.y - box1.Size.y - box2.Position.y) <= 2.0f) { normalX = CDirection::NONE_DIRECT; normalY = CDirection::ON_DOWN; entryTime = 0.0f; } else if (fabsf(box1.Position.y - (box2.Position.y - box2.Size.y)) <= 2.0f) { normalX = CDirection::NONE_DIRECT; normalY = CDirection::ON_UP; entryTime = 0.0f; } } } } else { if (box1.Velocity.y > 0.0f) { if (!(box1.Position.x + box1.Size.x <= box2.Position.x || box1.Position.x >= box2.Position.x + box2.Size.x)) { normalY = CDirection::ON_UP; normalX = CDirection::NONE_DIRECT; } else { if (fabsf(box1.Position.x + box1.Size.x - box2.Position.x) <= 2.0f) { normalY = CDirection::NONE_DIRECT; normalX = CDirection::ON_RIGHT; entryTime = 0.0f; } else if (fabsf(box1.Position.x - (box2.Position.x + box2.Size.x)) < 2.0f) { normalY = CDirection::NONE_DIRECT; normalX = CDirection::ON_LEFT; entryTime = 0.0f; } } } else { if (!(box1.Position.x + box1.Size.x <= box2.Position.x || box1.Position.x >= box2.Position.x + box2.Size.x)) { normalY = CDirection::ON_DOWN; normalX = CDirection::NONE_DIRECT; } else { if (fabsf(box1.Position.x + box1.Size.x - box2.Position.x) <= 2.0f) { normalY = CDirection::NONE_DIRECT; normalX = CDirection::ON_RIGHT; entryTime = 0.0f; } else if (fabsf(box1.Position.x - (box2.Position.x + box2.Size.x)) < 2.0f) { normalY = CDirection::NONE_DIRECT; normalX = CDirection::ON_LEFT; entryTime = 0.0f; } } } } return entryTime; } #pragma endregion }
bool CCollision::AABBCheck(CBox box1, CBox box2) { return box1.IsIntersectedWith(box2); }