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?

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.


É 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.


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.


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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.