Ok, então este é um problema que venho tentando descobrir há algum tempo. O Mine é um jogo de plataformas 2D com um mundo composto de (geralmente) blocos imóveis e sprites móveis, os quais usam AABBs para representar seus hitboxes. Este jogo NÃO é baseado em grade devido a algumas complicações com a movimentação de camadas de peças.
Eu posso detectar colisões e descobrir facilmente a profundidade da colisão. Eu uso o "método de eixo mais raso" para determinar qual caminho resolver uma colisão entre o sprite e o ladrilho. Se o sprite for mais profundo horizontalmente do que verticalmente, a direção a ser resolvida é para cima ou para baixo. Se o sprite for mais profundo verticalmente do que horizontalmente, a direção a ser resolvida é esquerda ou direita.
Isso é bastante simples e funciona muito bem. Ou seja, até que você tenha um sprite colidindo com mais de um bloco. Como, por sua natureza, cada colisão deve ser verificada separadamente, diferentes colisões podem ter uma direção diferente para resolver. Por exemplo, se um sprite estiver tentando atravessar uma fileira de ladrilhos, para um quadro, eles cruzarão o próximo ladrilho, como que a profundidade horizontal é menor que a profundidade vertical. Como a colisão diz "resolva à esquerda", ela será empurrada para trás e ficará presa na esquina.
Venho refletindo sobre esse problema há muito tempo, e há várias soluções para mim, mas todas têm falhas. Eu poderia marcar certos lados como inacessíveis, mas sem um mecanismo baseado em grade, a determinação de "inacessibilidade" é notavelmente complexa, especialmente com a possibilidade de mover camadas de ladrilhos sempre.
Outro método possível seria prever colisões antes que elas aconteçam e "retroceder" o movimento até o ponto da colisão, suponho, mas não tenho certeza de como a matemática funciona.
Sinto que estou perdendo algo incrivelmente óbvio, principalmente porque os jogos dos anos 80 já resolveram esse problema.
Respostas:
O problema
O problema está no seu método de resolução de colisões. Seu método é o seguinte:
O problema é que ele pode mover o jogador facilmente na direção errada. Você pode ver como isso pode acontecer na imagem abaixo:
Como o jogador está se movendo para a direita e está acima do solo, seria de esperar que ele caísse em cima do solo (pela caixa verde). Mas, em vez disso, ele é empurrado do chão para a esquerda (representado pela caixa vermelha). Isso pode ser um problema se o jogador estiver tentando pular de uma plataforma para outra, porque o jogador pode acabar morrendo devido a um código de colisão incorreto.
A solução
A solução para esse problema é realmente bastante simples. Em vez de usar o método acima, você resolve a colisão da seguinte maneira:
Agora, espero que você não tenha descartado seu código de verificação de profundidade, porque ainda precisará dele nas etapas 3 e 6.
Para resolver a colisão entre peças em qualquer um dos dois eixos (depois de mover o jogador), você primeiro obtém a profundidade da colisão. Você pega a profundidade da colisão e subtrai a dos eixos que você está verificando no momento. Observe que a profundidade deve ser negativa se você estiver se movendo para a esquerda, para que o jogador se mova na direção certa.
Usando esse método, você não apenas não precisará se preocupar com erros de colisão como o do cenário da imagem acima, mas também pode lidar com colisões com vários blocos.
Código de exemplo:
fonte
float
s para armazenar minhas coordenadas. Então estava causando tremores. A solução foi arredondar as cordas quando terminei de resolver a colisão.Você está pensando demais no problema e confundindo alguns problemas. Mas tudo bem, porque, como você disse, este é um problema muito resolvido, com muitas ótimas respostas por aí.
Vamos dividir:
Tilemaps . Seu primeiro exemplo é de um sprite andando por um monte de ladrilhos dispostos horizontalmente (ou deslizando por uma parede de ladrilhos dispostos verticalmente, eles são isomórficos). Uma solução muito elegante para isso é simplesmente não verificar as arestas dos ladrilhos onde sabemos que um sprite não pode chegar, como arestas "subterrâneas" ou arestas que fazem fronteira com outro ladrilho completamente sólido.
Você está certo de que o sprite desceria devido à gravidade, depois se moveria lateralmente e depois ficaria preso ... mas a resposta é não se importar com as bordas esquerda ou direita dos ladrilhos subterrâneos . Dessa forma, sua rotina de resolução de colisão apenas move o sprite verticalmente - e seu sprite pode seguir seu caminho alegre.
Confira os tutoriais do bloco Metanet para obter uma explicação passo a passo disso. Você diz na sua pergunta que não está usando um mapa de mosaico tradicional, mas tudo bem: mosaicos estáticos estão no mapa de mosaicos e são atualizados como acima, enquanto movem plataformas e atualizações como # 2 abaixo.
Outros AABBs . Você só terá problemas se, em um único quadro, seu sprite puder se mover uma distância maior que a largura / altura da maioria dos AABBs no seu jogo. Se não puder, você é de ouro: resolva as colisões uma por uma e funcionará bem.
Se os AABBs puderem se mover muito rápido em um único quadro, você deve "varrer" o movimento ao verificar colisões: divida o movimento em frações menores e verifique se há colisões em cada etapa.
fonte