Dado que esto se basa en su otra pregunta, daré una solución para cuando el rectángulo esté alineado con el eje.
Primero, construye el rectángulo de su objeto actual con los siguientes valores:
int boxLeft = box.X;
int boxRight = boxLeft + box.Width;
int boxTop = box.Y;
int boxBottom = boxTop + box.Height;
A continuación, debe tener la posición del objeto antiguo (que puede almacenar en cada objeto o simplemente pasar a una función) para crear el rectángulo del objeto antiguo (cuando no estaba colisionando):
int oldBoxLeft = box.OldX;
int oldBoxRight = oldBoxLeft + box.Width;
int oldBoxTop = box.OldY;
int oldBoxBottom = oldBoxTop + box.Height;
Ahora, para saber de dónde fue la colisión, debe encontrar el lado donde la posición anterior no estaba en el área de colisión y dónde está su nueva posición. Porque, cuando lo piensas, esto es lo que sucede cuando chocas: un lado que no colisionó entra en otro rectángulo.
Así es como podría hacerlo (estas funciones suponen que hay una colisión. No deberían llamarse si no hay colisión):
bool collidedFromLeft(Object otherObj)
{
return oldBoxRight < otherObj.Left && // was not colliding
boxRight >= otherObj.Left;
}
Enjuague y repita.
bool collidedFromRight(Object otherObj)
{
return oldBoxLeft >= otherObj.Right && // was not colliding
boxLeft < otherObj.Right;
}
bool collidedFromTop(Object otherObj)
{
return oldBoxBottom < otherObj.Top && // was not colliding
boxBottom >= otherObj.Top;
}
bool collidedFromBottom(Object otherObj)
{
return oldBoxTop >= otherObj.Bottom && // was not colliding
boxTop < otherObj.Bottom;
}
Ahora, para el uso real con la respuesta de colisión de la otra pregunta:
if (collidedFromTop(otherObj) || collidedFromBottom(otherObj))
obj.Velocity.Y = -obj.Velocity.Y;
if (collidedFromLeft(otherObj) || collidedFromRight(otherObj))
obj.Velocity.X = -obj.Velocity.X;
Una vez más, esta puede no ser la mejor solución, pero esa es la forma en que generalmente utilizo la detección de colisiones.