Esta é uma pergunta de "acompanhamento" da minha anterior, sobre detecção e resolução de colisões, que você pode encontrar aqui .
Se você não quiser ler a pergunta anterior, aqui está uma breve descrição de como meu mecanismo de física funciona:
Toda entidade física é armazenada em uma classe chamada SSSPBody.
Apenas AABBs são suportados.
Todo SSSPBody é armazenado em uma classe chamada SSSPWorld, que atualiza todos os corpos e lida com a gravidade.
A cada quadro, o SSSPWorld atualiza todos os corpos.
Todo corpo atualizado procura corpos próximos em um hash espacial, verifica se eles precisam detectar colisões com eles. Se sim, eles invocam um evento de "colisão" e verificam se precisam resolver colisões com eles. Se sim, eles calculam o vetor de penetração e a sobreposição direcional e alteram sua posição para resolver a penetração.
Quando um corpo colide com outro, transfere sua velocidade para o outro simplesmente ajustando a velocidade do corpo à sua.
Um corpo com velocidade é definido como 0 quando não mudou de posição a partir do último quadro. Se também colidir com um corpo em movimento (como um elevador ou uma plataforma em movimento), calcula a diferença de movimento do elevador para ver se o corpo não se moveu da sua última posição.
Além disso, um corpo chama um evento "esmagado" quando todos os seus cantos da AABB se sobrepõem a algo em um quadro.
Este é o código fonte COMPLETO do meu jogo. Está dividido em três projetos. SFMLStart é uma biblioteca simples que trata de entrada, desenho e atualização de entidades. SFMLStartPhysics é o mais importante, onde estão as classes SSSPBody e SSSPWorld. PlatformerPhysicsTest é o projeto do jogo, contendo toda a lógica do jogo.
E este é o método "update" na classe SSSPBody, comentado e simplificado. Você pode dar uma olhada apenas nisso se não estiver com vontade de olhar para todo o projeto SFMLStartSimplePhysics. (E mesmo que você faça isso, você ainda deve dar uma olhada nisso, pois é comentado.)
O gif mostra dois problemas.
- Se os corpos são colocados em uma ordem diferente, resultados diferentes acontecem. As caixas à esquerda são idênticas às caixas à direita, colocadas apenas na ordem inversa (no editor).
- Ambas as caixas devem ser movidas para o topo da tela. Na situação à esquerda, nenhuma caixa é lançada. À direita, apenas um deles é. Ambas as situações não são intencionais.
Primeiro problema: ordem da atualização
Isso é bastante simples de entender. Na situação à esquerda, a caixa superior é atualizada antes da outra. Mesmo que a caixa no fundo "transfira" a velocidade para a outra, ela precisa esperar o próximo quadro para se mover. Como não se moveu, a velocidade da caixa inferior é definida como 0.
Eu não tenho nenhuma idéia de como consertar isso. Prefiro que a solução não dependa da "classificação" da lista de atualizações, porque sinto que estou fazendo algo errado em todo o design do mecanismo de física.
Como os principais mecanismos de física (Box2D, Bullet, Chipmunk) lidam com a ordem de atualização?
Segundo problema: apenas uma caixa é lançada em direção ao teto
Ainda não entendo por que isso acontece. O que a entidade "mola" faz é definir a velocidade do corpo para -4000 e reposicioná-la sobre a própria mola. Mesmo se eu desativar o código de reposicionamento, o problema ainda ocorre.
Minha idéia é que, quando a caixa inferior colide com a caixa superior, sua velocidade é definida como 0. Não sei por que isso acontece.
Apesar da chance de parecer alguém que desiste do primeiro problema, publiquei todo o código-fonte do projeto acima. Não tenho nada para provar isso, mas acredite, tentei consertar isso, mas não consegui encontrar uma solução e não tenho nenhuma experiência anterior com física e colisões. Estou tentando resolver esses dois problemas há mais de uma semana e agora estou desesperada.
Acho que não consigo encontrar uma solução sozinho sem retirar muitos recursos do jogo (transferência de velocidade e molas, por exemplo).
Muito obrigado pelo tempo gasto lendo esta pergunta e ainda mais se você tentar encontrar uma solução ou sugestão.