Estou tentando criar um jogo de plataformas 2D (tipo Mario) e estou tendo alguns problemas ao lidar com colisões corretamente. Estou escrevendo este jogo em C ++, usando SDL para entrada, carregamento de imagens, carregamento de fontes, etc. Também estou usando o OpenGL através da biblioteca FreeGLUT em conjunto com o SDL para exibir gráficos.
Meu método de detecção de colisão é o AABB (Axis-Aligned Bounding Box), que é realmente tudo o que preciso para começar. O que eu preciso é de uma maneira fácil de detectar em que lado a colisão ocorreu e lidar adequadamente com as colisões. Então, basicamente, se o jogador colidir com o topo da plataforma, reposicione-o no topo; se houver colisão com os lados, reposicione o jogador de volta ao lado do objeto; se houver uma colisão no fundo, reposicione o player embaixo da plataforma.
Eu tentei muitas maneiras diferentes de fazer isso, como tentar encontrar a profundidade da penetração e reposicionar o player para trás pela profundidade da penetração. Infelizmente, nada do que tentei parece funcionar corretamente. O movimento do jogador acaba sendo muito problemático e reposiciona o jogador quando eu não quero. Parte do motivo é provavelmente porque sinto que isso é algo tão simples, mas estou pensando demais.
Se alguém achar que pode ajudar, dê uma olhada no código abaixo e me ajude a tentar melhorar isso, se puder. Eu gostaria de não usar uma biblioteca para lidar com isso (como quero aprender por conta própria) ou algo como o SAT (Teorema do Eixo Separador), se possível. Agradeço antecipadamente por sua ajuda!
void world1Level1CollisionDetection()
{
for(int i; i < blocks; i++)
{
if (de2dCheckCollision(ball,block[i],0.0f,0.0f)==true)
{
de2dObj ballPrev;
ballPrev.coords[0] = ball.coords[0];
ballPrev.coords[1] = ball.coords[1];
ballPrev.coords[2] = ball.coords[2];
ballPrev.coords[3] = ball.coords[3];
ballPrev.coords[0] -= ball.xspeed;
ballPrev.coords[1] -= ball.yspeed;
ballPrev.coords[2] -= ball.xspeed;
ballPrev.coords[3] -= ball.yspeed;
int up = 0;
int left = 0;
int right = 0;
int down = 0;
if (ballPrev.coords[0] < block[i].coords[0] && ballPrev.coords[2] < block[i].coords[0] && (((ball.coords[1] < block[i].coords[1]) || (ball.coords[3] < ball.coords[1])) || ((ball.coords[1] < block[i].coords[3]) || ball.coords[3] < block[i].coords[3])))
{
left = 1;
}
if (ballPrev.coords[0] > block[i].coords[2] && ballPrev.coords[2] > block[i].coords[2] && (((ball.coords[1] < block[i].coords[1]) || (ball.coords[3] < ball.coords[1])) || ((ball.coords[1] < block[i].coords[3]) || (ball.coords[3] < block[i].coords[3]))))
{
right = 1;
}
if(ballPrev.coords[1] < block[i].coords[1] && block[i].coords[1] < ballPrev.coords[3] && ballPrev.coords[3] < block[i].coords[3])
{
up = 1;
}
if(block[i].coords[1] < ballPrev.coords[1] && ball
{
down = 1;
}
cout << left << ", " << right << ", " << up << ", " << down << ", " << endl;
if (left == 1)
{
ball.coords[0] = block[i].coords[0] - 18.0f;
ball.coords[2] = block[i].coords[0] - 2.0f;
}
else if (right == 1)
{
ball.coords[0] = block[i].coords[2] + 2.0f;
ball.coords[2] = block[i].coords[2] + 18.0f;
}
else if (down == 1)
{
ball.coords[1] = block[i].coords[3] + 4.0f;
ball.coords[3] = block[i].coords[3] + 20.0f;
}
else if (up == 1)
{
ball.yspeed = 0.0f;
ball.gravity = 0.0f;
ball.coords[1] = block[i].coords[1] - 17.0f;
ball.coords[3] = block[i].coords[1] - 1.0f;
}
}
if (de2dCheckCollision(ball,block[i],0.0f,0.0f)==false)
{
ball.gravity = -0.5f;
}
}
}
Para explicar o que parte desse código significa:
A variável de blocos é basicamente um número inteiro que está armazenando a quantidade de blocos ou plataformas. Estou verificando todos os blocos usando um loop for e o número em que o loop está atualmente é representado pelo número inteiro i. O sistema de coordenadas pode parecer um pouco estranho, então vale a pena explicar. as cordas [0] representam a posição x (esquerda) do objeto (onde começa no eixo x). as cordas [1] representam a posição y (em cima) do objeto (onde começa no eixo y). as cordas [2] representam a largura do objeto mais as cordas [0] (direita). as cordas [3] representam a altura do objeto mais as cordas [1] (embaixo). de2dCheckCollision executa uma detecção de colisão AABB. Up é negativo y e down é positivo y, como na maioria dos jogos.
Espero ter fornecido informações suficientes para alguém me ajudar com sucesso. Se houver algo que deixei de fora que possa ser crucial, informe-me e fornecerei as informações necessárias. Finalmente, para quem puder ajudar, fornecer código seria muito útil e muito apreciado.
Obrigado novamente por sua ajuda!
Edit : Eu atualizei meu código com um novo algoritmo que verifica onde a bola estava anteriormente antes da colisão. Os estojos de canto funcionam nessa plataforma única corretamente agora, mas quando tenho uma parede de objetos, consigo deslizar contra ela, mas se me mover em direção à parede enquanto deslizo, passo por ela e agora estou essencialmente em cima de uma bloco dentro da parede. Além disso, há um efeito de tremor que acontece quando estou no chão, onde a bola está constantemente subindo e descendo.
TheirPos-ourSize +- 1
remover o 1, se é isso que você está fazendo. Se você não é apenas certo como obter esse algoritmo descobri que eu seria mais do que dispostos a ajudar, o meu é perfeito no momento =] (também que ordem você está verificando os objetos?)