Em um jogo de plataforma 2D, como garantir que o jogador se mova suavemente sobre terreno inclinado?

18

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.

Nick Kovac
fonte
Um mecanismo de física geral é ótimo para efeitos e caixas de queda e tudo mais, mas não para a física dos personagens, conforme descrito na seção de respostas. Considere escrever física "estática" para o seu personagem, para que você possa ter 100% de controle e use a dinâmica simulada adequadamente para o resto.
Domi

Respostas:

14

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.

Sean Middleditch
fonte
Obrigado pela sua resposta. Eu havia pensado em reduzir as caixas que representam o terreno em linhas, mas, na verdade, não acho que isso por si só resolva o problema. Por exemplo, se as caixas de solo agora estiverem em linhas e se o jogador estiver na linha C e estiver viajando para a esquerda em direção a B, devido à imprecisão, é possível que a caixa do jogador esteja um pouco abaixo da linha C. Em seguida, a borda esquerda da caixa do jogador ainda poderia colidir com a linha B e causa que colisão indesejável,
Nick Kovac
a menos que haja algum outro mecanismo para impedir que isso aconteça. Não é o fato de o Box2D usar linhas em vez de caixas que resolve o problema, mas o Box2D usa um formato de corrente, que usa informações de conectividade entre os segmentos de linha para impedir que algumas colisões aconteçam. O principal problema no momento é que não entendo bem os detalhes de como exatamente isso é feito.
Nick Kovac
Você levantou outros pontos realmente bons sobre os problemas em obter idéias de mecanismos genéricos de física e aplicá-las a jogos de plataforma. Eu já vi motores semelhantes que implementam as idéias que você discutiu (modificando a colisão normal para pistas e sugando o jogador para a pista); portanto, pelo menos esses problemas são facilmente solucionáveis. O principal ponto de discórdia para mim são os casos complicados relacionados a erros numéricos.
Nick Kovac
@Kovsa: novamente, esses erros específicos desaparecem quando você se livra das bordas que não deveriam fazer parte da colisão. Encadeie as bordas para formar uma forma ininterrupta. Ao projetar seu nível, também recomendo encaixar os vértices para que você não tenha pequenas fendas nas superfícies. Na verdade, não é diferente de como você projeta o nível em um editor de malha 3D.
27512 Sean Sean Middleditch
Hum ... acho que não sigo. No meu diagrama, se eu amarrei as arestas para criar uma forma ininterrupta, obteria uma forma composta por três segmentos de linha: a parte superior das caixas A, B e C, certo? Mesmo sendo uma forma única, eu ainda precisaria executar a detecção de colisão separadamente na linha A, depois B e C, não? A menos que você tenha pensado em um algoritmo que pode detectar uma colisão entre a caixa e essa forma combinada? Estou assumindo que não seria SAT, pois uma série de arestas poderia ser côncava?
precisa
5

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.

Kevin Reid
fonte
Hmm, ideia interessante ... como você implementaria isso? Porém, isso contraria a simplicidade do uso de caixas: (Concordo que parece ser um problema comum com uma solução definitiva, mas não consigo encontrar realmente nenhuma cobertura sobre isso ... além do que está sendo feito . em Box2D eu postei uma pergunta semelhante em seu fórum para espero obter mais conhecimento.
Nick Kovac
Não tenho detalhes de implementação, desculpe - não sou especialista nesse tipo de código de mecanismo de física. No entanto, tive uma idéia melhor para uma solução que não se baseia em fatores de falsificação - veja minha edição.
Kevin Reid
11
Observe que, embora o uso de formas arredondadas funcione, é matematicamente mais complexo e pode resultar em um comportamento abaixo do ideal para os participantes da plataforma. Os jogadores esperam ter um controle quase perfeito em pixels sobre os personagens que estão nas bordas, por exemplo, que formas arredondadas tornarão mais ou menos impossíveis e os personagens deslizarão das bordas inesperadamente.
precisa
Ledges: D'oh! OK, não é tão simples quanto eu pensava.
Kevin Reid
Sim, depois de pensar nisso, a abordagem cápsula parece talvez mais adequada para um jogo em 3D do que para um jogo de plataformas em 2D. Ter controle perfeito de pixel é definitivamente uma prioridade para mim (como era em todos aqueles antigos plataformas 2D). Mas deve haver uma solução que permita o uso de caixas!
Nick Kovac