Вот простой тест столкновения коробки. Это, очевидно, очень просто, подождите, пока вы не проведете тестирование столкновения полигонов!
//! (collision detection)
inline BOOL Sprite::TestCollision(Sprite* pTestSprite)
{
//! Get the collision box.
RECT& rcTest = pTestSprite->GetCollision();
//! box collision check.
return m_rcCollision.left <= rcTest.right && rcTest.left <= m_rcCollision.right &&
m_rcCollision.top <= rcTest.bottom && rcTest.top <= m_rcCollision.bottom;
}
Теперь, что делать, чтобы остановить спрайт или отскок или что-то еще, это выглядит примерно так:
(Примечание: в этом случае проверяется столкновение с границей, но в основном то же самое выполняется с другими объектами). Если это просто выровненное по оси столкновения поле, все, что вам нужно сделать, это выровнять объект столкновения с горизонтальным или вертикальным краем другого объекта столкновения. Если объект сталкивается с левой стороны, выровняйте по левому краю другого объекта. Просто. Измените скорости соответственно, если вы хотите отскочить или остановиться.
В этом примере я создаю тестовые переменные с обновленной позицией, а затем выполняю тест на столкновение, затем выполняю процедуру ниже или просто устанавливаю новую позицию, если столкновения нет.
Поэтому мы на самом деле исправляем это до того, как произойдет столкновение.
// Update the position
POINT ptNewPosition, ptSpriteSize, ptBoundsSize;
ptNewPosition.x = m_rcPosition.left + m_ptVelocity.x;
ptNewPosition.y = m_rcPosition.top + m_ptVelocity.y;
ptSpriteSize.x = m_rcPosition.right - m_rcPosition.left;
ptSpriteSize.y = m_rcPosition.bottom - m_rcPosition.top;
ptBoundsSize.x = m_rcBounds.right - m_rcBounds.left;
ptBoundsSize.y = m_rcBounds.bottom - m_rcBounds.top;
// Check the bounds
// Wrap?
if (m_baBoundsAction == BA_WRAP)
{
if ((ptNewPosition.x + ptSpriteSize.x) < m_rcBounds.left)
ptNewPosition.x = m_rcBounds.right;
else if (ptNewPosition.x > m_rcBounds.right)
ptNewPosition.x = m_rcBounds.left - ptSpriteSize.x;
if ((ptNewPosition.y + ptSpriteSize.y) < m_rcBounds.top)
ptNewPosition.y = m_rcBounds.bottom;
else if (ptNewPosition.y > m_rcBounds.bottom)
ptNewPosition.y = m_rcBounds.top - ptSpriteSize.y;
}
// Bounce?
else if (m_baBoundsAction == BA_BOUNCE)
{
BOOL bBounce = FALSE;
POINT ptNewVelocity = m_ptVelocity;
if (ptNewPosition.x < m_rcBounds.left)
{
bBounce = TRUE;
ptNewPosition.x = m_rcBounds.left;
ptNewVelocity.x = -ptNewVelocity.x;
}
else if ((ptNewPosition.x + ptSpriteSize.x) > m_rcBounds.right)
{
bBounce = TRUE;
ptNewPosition.x = m_rcBounds.right - ptSpriteSize.x;
ptNewVelocity.x = -ptNewVelocity.x;
}
if (ptNewPosition.y < m_rcBounds.top)
{
bBounce = TRUE;
ptNewPosition.y = m_rcBounds.top;
ptNewVelocity.y = -ptNewVelocity.y;
}
else if ((ptNewPosition.y + ptSpriteSize.y) > m_rcBounds.bottom)
{
bBounce = TRUE;
ptNewPosition.y = m_rcBounds.bottom - ptSpriteSize.y;
ptNewVelocity.y = -ptNewVelocity.y;
}
if (bBounce)
SetVelocity(ptNewVelocity);
}
// v0.1.1 (collision detection)
// Die?
else if (m_baBoundsAction == BA_DIE)
{
if ((ptNewPosition.x + ptSpriteSize.x) < m_rcBounds.left || ptNewPosition.x > m_rcBounds.right
|| (ptNewPosition.y + ptSpriteSize.y) < m_rcBounds.top || ptNewPosition.y > m_rcBounds.bottom)
return SA_KILL;
}
// v0.1.1 ----------------------
// Stop (default)
else
{
if (ptNewPosition.x < m_rcBounds.left || ptNewPosition.x > (m_rcBounds.right - ptSpriteSize.x))
{
ptNewPosition.x = max(m_rcBounds.left, min(ptNewPosition.x, m_rcBounds.right - ptSpriteSize.x));
SetVelocity(0, 0);
}
if (ptNewPosition.y < m_rcBounds.top || ptNewPosition.y > (m_rcBounds.bottom - ptSpriteSize.y))
{
ptNewPosition.y = max(m_rcBounds.top, min(ptNewPosition.y, m_rcBounds.bottom - ptSpriteSize.y));
SetVelocity(0, 0);
}
}