Se eu souber que uma determinada ação resultará em uma colisão, devo permitir que a ação ocorra de qualquer maneira?

7

Eu terminei de programar meu mecanismo de jogo e agora que o testei, percebi alguns problemas gráficos.

O grande problema é que, quando um jogador tenta empurrar contra uma parede, seu personagem "balança" contra ela, enquanto tenta constantemente entrar no espaço da parede e a detecção de colisão constantemente a empurra de volta para fora.

Qual é a maneira correta de lidar com essa situação?

Meu primeiro instinto foi que, se mover em uma certa direção causa uma colisão, desabilite o movimento nessa direção até que a posição da entidade mude. Ou seja, quando um objeto cair em uma plataforma, desative a gravidade até que o objeto não esteja mais acima de uma plataforma.

Existe uma maneira melhor de resolver detecções de colisão repetidas entre os mesmos dois objetos no mesmo espaço sobreposto?

Sonhador Corvo
fonte

Respostas:

5

Sobre colisões de caracteres com uma parede, por exemplo (usarei alguns valores arbitrários como exemplo): se você estiver a 10 unidades (por exemplo, pixels) de uma parede, e um único passo normalmente o moveria 20 unidades nessa direção, o O comportamento correto é que seu personagem mova 10 unidades e pare por aí. Se você cancelou a ação, você permaneceria a 10 unidades da parede, o que não é o que você deseja.

Uma maneira de fazer isso é mover o personagem pela quantidade total, depois detectar a colisão e sua profundidade, ou seja, quanto as caixas delimitadoras do personagem e da parede estão sobrepostas, e mover o personagem de volta nessa mesma quantidade. Se você fizer isso corretamente, você não deve ter nenhum comportamento de "jiggle" do seu personagem, ele simplesmente pressiona a parede e para por aí. Se ele estiver balançando, provavelmente você o está movendo de volta demais (provavelmente você está movendo-o de volta para a posição que ele estava antes da colisão, em vez de prendê-lo contra o limite da parede).

Dito isto, normalmente vejo a gravidade sendo tratada como um caso especial. Na maioria das implementações que vi, o personagem armazena uma onFloorbandeira e a gravidade é aplicada apenas quando essa bandeira é falsa.

Edit: Eu acho que você poderia expandir esse último conceito e criar sinalizadores adicionais como touchingRightWallor touchingLeftWall, mas apenas quando os limites do personagem e da parede corresponderem exatamente . Nesse caso, talvez você possa ignorar completamente o movimento. Porém, se os limites não corresponderem com precisão, você deve permitir que o movimento ocorra e o sistema de detecção de colisão resolva quaisquer interseções.

David Gouveia
fonte
É assim que estou lidando com colisões, atualmente. O "jiggle" parece mais com o sprite que está vibrando do que com uma quantidade detectável de avanço / retrocesso.
Raven Dreamer
2
Você está calculando a profundidade da interseção corretamente? Tente depurar os valores de posição do personagem e a profundidade da interseção contra os que você esperaria ter. Eu fiz isso antes sem vibrações. Também pode haver algum problema de ponto flutuante de subpixel? Se for esse o caso, tente arredondar seus valores. E, finalmente, verifique a amostra de plataformas do XNA.
David Gouveia
Honestamente, acho que é apenas porque a IO (que move a entidade) acontece em um momento diferente da detecção de colisão, o que significa que as duas entidades se sobrepõem até que o mecanismo de jogo chegue ao loop de atualização do subsistema de colisão.
Corvo Dreamer
Mas os subsistemas de E / S e detecção de colisão não estão sendo atualizados na mesma iteração do seu loop de atualização? A única maneira de ver isso fazendo diferença é se o seu loop de renderização estiver completamente separado e puder ser chamado de alguma forma entre as atualizações dos seus subsistemas ou se você estiver estendendo esse processamento entre vários quadros.
David Gouveia
Todo o processo geralmente será [IO -> Detecção de colisão -> Resolução de colisão] -> [Renderização]. Mesmo que as partes Update e Render sejam chamadas em taxas diferentes, você nunca poderá ver seus objetos renderizados em algum estado intermediário (ou seja, após IO, mas antes da detecção de colisão, ou após a detecção de colisão, mas antes da resolução da colisão). Você sempre verá seu personagem renderizado após a aplicação de todos os estágios da atualização; portanto, não importa se eles são processados ​​em etapas diferentes ou não.
David Gouveia
2

Esse problema geralmente ocorre quando o código prende as posições antes de detectar uma colisão. Ou seja:

MoveCharacter();
ClampPosition();
CheckCollision();
DrawFrame();

ao invés de

MoveCharacer();
CheckCollision();
ClampPosition();
DrawFrame();

A razão pela qual ele "balança" é porque a verificação acontece depois que o personagem foi fixado em um local "seguro", mas porque o personagem está em um local sem colisão no momento da verificação, o mecanismo permite que o personagem continue a mover, então o personagem é desenhado e, no próximo quadro, a verificação falha, Clamp é chamado, fazendo com que o personagem volte ao local seguro.

Casey
fonte
11
Realmente não vejo como isso faz sentido. Como o grampo poderia acontecer antes de verificar se há colisões se você precisar dos resultados de suas colisões contra quais valores fixar em primeiro lugar?
David Gouveia
O que realmente está acontecendo é que o personagem está sendo desenhado antes de ser movido para o local correto no próximo quadro, em vez de ser movido para o local correto antes do desenho atual .
Casey #
0

Eu tive o mesmo problema recentemente e o corrigi assim:

mova o objeto, verificando se há uma colisão; se for encontrada uma colisão, coloque o objeto fora do objeto em colisão. desenhe o objeto.

O jogador pode continuar correndo contra a parede sem balançar, porque antes de ser sorteado, ele será colocado ao lado do objeto.

Johan
fonte
0

Usando a matemática vetorial / plano, você pode calcular o ponto exato de colisão com a parede que ocorrerá no próximo quadro. Isso pressupõe que seu personagem tenha velocidade que você pode usar para calcular o vetor de movimento que ocorrerá durante o próximo quadro. Depois de encontrar o ponto de colisão, você pode calcular o vetor deslizante que moverá seu personagem ao longo da parede, na verdade esse vetor pode colidir com outra parede.

Então, voltando à sua pergunta, você deve calcular a posição exata da colisão onde seu personagem deve estar localizado e o que realmente deve acontecer. Se esta é uma parede e seu jogo FPS, deixe o personagem deslizar ao longo dela.

marcinj
fonte