Estou desenvolvendo um mecanismo de física para um jogo de plataforma 2D. Estou usando o teorema do eixo separador para detecção de colisão. A superfície do solo é construída a partir de caixas delimitadoras orientadas, com o jogador como uma caixa delimitadora alinhada ao eixo. (Especificamente, estou usando o algoritmo do livro "Realtime Collision Detection", que executa a detecção de colisão por varredura para OBBs usando SAT). Estou usando um coeficiente de restituição razoavelmente pequeno (próximo a zero) na resposta à colisão, para garantir que os objetos dinâmicos não penetrem no ambiente.
O mecanismo geralmente funciona bem, mas estou preocupado com alguns casos extremos que podem ocorrer. Por exemplo, no diagrama, A, B e C são a superfície do solo. O jogador está indo para a esquerda ao longo de B em direção a A. Parece-me que, devido à imprecisão, a caixa do jogador pode estar um pouco abaixo da caixa B à medida que continua subindo e saindo. Quando atinge A, portanto, o canto inferior esquerdo do jogador pode colidir com o lado direito de A, o que seria indesejável (pois a intenção é que o jogador se mova suavemente sobre o topo de A). Parece que um problema semelhante pode acontecer quando o jogador está no topo da caixa C, movendo-se para a esquerda em direção a B - o ponto mais extremo de B pode colidir com o lado esquerdo do jogador, em vez de o canto inferior esquerdo do jogador deslizar para cima e para a esquerda acima de B.
O Box2D parece lidar com esse problema armazenando informações de conectividade para suas formas de borda, mas não tenho muita certeza de como ele usa essas informações para resolver o problema e, depois de analisar o código, não entendo o que está fazendo.
Todas as sugestões serão muito apreciadas.
Respostas:
Plataformas e Física
Esses casos extremos são numerosos. Plataformas divertidas e divertidas não se comportam de nenhuma maneira fisicamente precisa, e o controle e o comportamento que os jogadores esperam depois de anos de plataformas "perfeitas" como Mario são incrivelmente difíceis de implementar com técnicas gerais, como as do Box2D ou outros mecanismos de física. A maioria das boas plataformas não usa nenhum tipo de resposta física ou de colisão genérica em seus controladores de player.
Gerar Cascos
Em relação à sua pergunta específica, a melhor solução é parar de usar caixas como base. Use uma série de segmentos de linha conectados (um casco). Isso permite que o mecanismo de detecção de colisão se concentre apenas nas superfícies passíveis de percorrer e não observe a borda "falsa" que existe entre AB e BC. Isso é o que o Box2D faz, de fato. As formas são usadas para gerar as superfícies externas, que são ligadas entre si para formar um casco.
Você precisa disso mesmo em jogos baseados em blocos ou em situações em que você tem dois objetos AABB ao lado de outros que atuam como piso. O mecanismo de colisão capta as arestas verticais e faz com que o jogador as pegue. Existem hacks que podem ajudar, mas não eliminar o problema. A solução é ter apenas um único segmento de linha representando a superfície, em vez de uma caixa 2D completa.
Você pode gerar os cascos no caso genérico cortando os polígonos um contra o outro e juntando os pontos do clipe em uma lista de arestas.
Superfícies inclinadas
Como seu exemplo inclui uma inclinação e você menciona restituição e outras propriedades físicas, mostrarei alguns outros problemas que você notará em breve, o que ilustra ainda mais por que a detecção e resposta genéricas de colisão não funcionam bem para os desenvolvedores de plataformas. Primeiro, tente ficar de pé na plataforma angular, pule para cima e depois aterrisse. Você provavelmente notará que o personagem "deslizará" um pouco ao pousar. O problema é que o contato normal que você está gerando geralmente estará apontando da superfície angular. Então, ao resolver a colisão, o jogador é empurrado nessa direção. Mesmo que o personagem tenha caído direto, ele será empurrado para cima e um pouco para a direita ao pousar, resultando no slide. Isso pode ser invadido levando em consideração as velocidades relativas,
O segundo problema que você notará, que é muito mais difícil de resolver, é o que acontece quando você tenta descer rapidamente uma rampa. O jogador vai "pular" a rampa. Isso é muito visível mesmo na maioria dos jogos AAA hoje. Não apenas parece bobo, mas se o seu jogo exige que o jogador seja pisado no chão para pular, torna difícil descer uma rampa e pular pela metade, porque o jogador está apenas entrando em contato com a rampa durante uma pequena parte do jogo. tempo gasto indo para baixo. Uma solução mais simples é simplesmente fazer alguns lançamentos de raios quando o jogador se move e encaixar a posição do jogador na superfície mais próxima (se estiver muito perto do jogador) se o jogador não estiver pulando e já estava no chão.
Você também pode achar que o jogador se lança no ar ao subir uma rampa, se tentar modelar velocidade, atrito e restituição no jogador como se ele fosse um corpo rígido normal. O movimento do jogador deve ser restrito ao movimento horizontal, a menos que caia / pule. Obviamente, se você joga plataformas mais antigas da idade de ouro, pode notar que a velocidade horizontal do jogador geralmente é constante entre superfícies horizontais e inclinadas. Isso também deve ser levado em consideração ao subir e descer ladeiras.
Haverá vários outros casos de canto estranhos nos quais você eventualmente encontrará também. Se você está tentando criar um bom jogo de plataformas, é realmente melhor implementar um controlador de jogador de plataformas separado da física e codificar o comportamento de movimento e controle que você deseja, em vez de confiar no algoritmo genérico de resposta física e física.
fonte
Penso que ambos os problemas poderiam ser resolvidos tratando suas caixas, para fins de resposta a colisões, como se tivessem cantos arredondados (de um raio semelhante ao seu erro numérico). Isso tornará a superfície combinada eficaz dos cantos da reunião entre A e B e B e C mais suave.
Assim, se o PLAYER se mover para a esquerda acertar o canto de A, a colisão normal seria diagonal e não puramente para a direita, permitindo a continuação do movimento de esquerda e para cima.
No entanto, uma solução mais típica, ao revisar o que sei da física de plataformas, é tornar o jogador com uma forma mais altamente arredondada e deixar o terreno em paz. Em particular, considere transformar a forma do jogador em uma cápsula (círculo esticado no meio (2D) / esfera (3D)) - então suas normais de colisão serão naturalmente quase verticais, eliminando qualquer problema de captura.
Você diz que está usando um algoritmo de colisão especificamente para OBBs, mas ainda deve, depois de encontrar uma colisão OBB-OBB, usar um teste adicional contra uma forma inteiramente dentro do OBB.
fonte