Como isso se baseia em sua outra pergunta, darei uma solução para quando o retângulo estiver alinhado ao eixo.
Primeiro, você constrói o retângulo do objeto atual com os seguintes valores:
int boxLeft = box.X;
int boxRight = boxLeft + box.Width;
int boxTop = box.Y;
int boxBottom = boxTop + box.Height;
Em seguida, você deve ter a posição do objeto antigo (que você pode armazenar em cada objeto ou simplesmente passar para uma função) para criar o retângulo do objeto antigo (quando não estava colidindo):
int oldBoxLeft = box.OldX;
int oldBoxRight = oldBoxLeft + box.Width;
int oldBoxTop = box.OldY;
int oldBoxBottom = oldBoxTop + box.Height;
Agora, para saber de onde a colisão ocorreu, você deve encontrar o lado em que a posição antiga não estava na área de colisão e onde está a nova posição. Porque, quando você pensa sobre isso, é o que acontece quando você colide: um lado que não estava colidindo entra em outro retângulo.
Aqui está como você pode fazer isso (essas funções assumem que há uma colisão. Elas não devem ser chamadas se não houver colisão):
bool collidedFromLeft(Object otherObj)
{
return oldBoxRight < otherObj.Left && // was not colliding
boxRight >= otherObj.Left;
}
Rince e 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;
}
Agora, para o uso real com a resposta de colisão da outra pergunta:
if (collidedFromTop(otherObj) || collidedFromBottom(otherObj))
obj.Velocity.Y = -obj.Velocity.Y;
if (collidedFromLeft(otherObj) || collidedFromRight(otherObj))
obj.Velocity.X = -obj.Velocity.X;
Novamente, essa pode não ser a melhor solução, mas é assim que costumo seguir para a detecção de colisões.