De acordo com a resposta de larsbutler, em casos simples, não importa se você verifica primeiro as colisões x ou y. No entanto, isso pode levar rapidamente à imprecisão, mais tarde no caminho (especialmente com formas mais complexas, maiores velocidades e mais objetos).
Se alguém estiver interessado em implementar um algoritmo de detecção de colisão mais sofisticado, aqui está um resumo do que é necessário:
- Primeiro, o algoritmo faz uma varredura e poda para diminuir o número de objetos necessários para verificar. Se você estiver verificando cada objeto em relação a qualquer outro objeto, pode ser bastante caro, computacionalmente. Basicamente, você prevê se um objeto provavelmente colidirá no futuro; se não for muito provável, você não faz os cálculos.
- Após a poda, você executa um teste de colisão preliminar. Cada objeto possui um retângulo ou círculo delimitador (algo fácil de calcular colisões). Detectar se dois círculos / retângulos colidem é bastante simples e pode eliminar rapidamente cálculos desnecessários entre dois objetos em lados opostos da tela.
- Se uma detecção preliminar foi feita, você precisa percorrer as bordas de cada forma e detectar pontos de colisão (interseção de dois segmentos de linha). No caso de Jon, este seria o ponto de colisão no eixo vertical e no eixo horizontal.
- Depois de ter uma lista de pontos de colisão, você precisa calcular o ponto de colisão exato . Existem várias maneiras de fazer isso, e tudo depende da precisão que você deseja ser. Uma opção é a metade do incremento de tempo (do seu integrador física ), recalcular as posições das formas, e executar novamente a detecção de colisão até que não é apenas um ponto de colisão. Basicamente, você está se aproximando do "momento do impacto". Se a sua simulação não possui muitas forças diferenciais parciais, você pode simplesmente usar a velocidade da integração anterior, com reduções de tempo subsequentes.
- Os resultados da etapa quatro fornecerão os pontos de colisão aproximados (dentro de um limite superior / inferior, como 3px ou algo assim). Se houver mais de um ponto de colisão, você terá que tratá-los como uma aresta imaginária. Você pode executar cálculos de resolução de colisão (velocidade, momento, fricção, etc.)
Espero que isso ajude alguém.
Específico à pergunta de Jon:
A etapa que está faltando no algoritmo de colisão é a etapa 4. Pelo que entendi, seus retângulos se cruzam na diagonal e acabam recebendo dois pontos de colisão (um na horizontal e outro na vertical). Determinar qual ponto de colisão ocorreu primeiro depende realmente do que você está usando para a integração da física.
Pela sua descrição, parece que os retângulos não giram e coisas como forças diferenciais parciais não são motivo de grande preocupação. Se for esse o caso, descobrir qual borda colide primeiro é bastante simples. Aqui está algum pseudo-código:
/*
Assume Obj1 is stationary
Assume Obj2's velocity is -x and -y (to bottom left)
From this, we know the collision edges are:
*/
colEdgesObj1 = [1,0]; //right, top
colEdgesObj2 = [0,1]; //left, bottom
//... where [0=left/1=right, 0=top/1=bottom]
//Calculate distances between Obj1 edges and Obj2 edges
distX = Math.Abs(Obj1[colEdgesObj1[0] ? "right" : "left"] -
Obj2[colEdgesObj2[0] ? "right" : "left"]);
distY = Math.Abs(Obj1[colEdgesObj1[1] ? "bottom" : "top"] -
Obj2[colEdgesObj2[1] ? "bottom" : "top"]);
//Calculate time object would take to go those distances
//(assuming Obj2 is the only moving object)
timeX = distX/Obj2.VelX;
timeY = distY/Obj2.VelY;
//If time is greater, that axis has been colliding longer
if timeX > timeY
//collided X axis first
else if timeY > timeX
//collided Y axis first
else
//collided at a corner