Here is a simple box collision test. It's obviously very simple, wait till you do polygon collision testing!
//! (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;
}
Now as far as what to do to stop the sprite or bounce or whatever, it goes something like so:
(Note: this case is checking collision against a boundary, but basically the same thing is performed with other objects). If it's just axis aligned box collision, all you have to do is align the collision object with the horizontal or vertical edge of the other collision object. If the object collides from the left side, align to the left edge of the other object. Simple. Change the velocities accordingly if you want rebounding or stopping.
In this example, I make test variables with the updated position and then do a collision test, then perform the routine below or just set the new position if no collision.
So we are actually fixing it before the collision happens.
// 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);
}
}