CCV_HEALbra
07-01-2008, 03:19 PM
aew galera..depois de um tempinho..achei algo interessante aqui!!
do site: http://blog.renatolouro.com/?cat=3
Como alguns sabem estou fazendo um curso de desenvolvimento de games. Neste, brincamos na aula passada de animar um personagem e detectar colisões. Mas parece que o algorítimo da aula passada para detectar colisões está com algum erro.
Estou desenvolvendo nas horas vagas, para treinar C e SDL, o SDLSoccer, que atualmente está mais para WarSoccer :-) . Num próximo post conto a história deste projeto para vocês. Mas o importante é que eu estava tentando utilizar a função para impedir que os jogadores entrem um dentro do outro, dando um efeito meio ‘fantasma’. Mas com a rotina de colisão que estava usando, nada dava certo. E depois de muito depurar, cheguei a conclusão que o erro tinha que estar nela. Então acabei fazendo um mais simples.
Se detectar colisão em retangulos é relativamente simples, mais simples ainda é detectar quando não ocorre a colisão, que foi a lógica que adotei.
Vamos lá:
Sendo r1 e r2 os retângulos 1 e 2 podemos afirmar que não haverá colisão de r1 estiver todo a direita ou todo a esquerda de r2. Ou seja se r1.x+r1.w<r2.x ou r1.x>r2.x+r2.w conforme mostra o diagrama abaixo:
http://blog.renatolouro.com/wp-content/uploads/2006/11/colide1.JPG
Caso contrário, ainda podemos afirmar não haverá colisão se r1 estiver totalmente acima ou totalmente abaixo de r2. Ou seja se r1.y+r1.h<r2.y ou r1.y>r2.y+r2.h conforme mostra o diagrama abaixo:
http://blog.renatolouro.com/wp-content/uploads/2006/11/colide2.JPG
Caso contrário, se r1 não está nem totalmente acima ou totalmente abaixo ou totalmente a direita ou ainda a esquerda, então afirmamos que existe colisão!
Com isso o código que era:
bool colidiu(SDL_Rect r1, SDL_Rect r2)
{
if ((r1.x >= r2.x && r1.x <= (r2.x + r2.w) &&
r1.y >= r2.y && r1.y <= (r2.y + r2.h)) ||
((r1.x + r1.w) >= r2.x && (r1.x + r1.w) <= (r2.x + r2.w) &&
(r1.y + r1.h) >= r2.y && (r1.y + r1.h) <= (r2.y + r2.h)))
return true;
}
Transformamos em algo mais simples e, no mínimo, mais legível:
bool colidiu(SDL_Rect r1, SDL_Rect r2)
{
if(r1.x+r1.w<r2.x || r1.x>r2.x+r2.w) return false;
if(r1.y+r1.h<r2.y || r1.y>r2.y+r2.h) return false;
return true;
}
ou ainda, numa forma ainda mais simples:
bool colidiu(SDL_Rect r1, SDL_Rect r2)
{
if((r1.x+r1.w<r2.x || r1.x>r2.x+r2.w) || (r1.y+r1.h<r2.y || r1.y>r2.y+r2.h)) return false;
return true;
}
Abraços!
do site: http://blog.renatolouro.com/?cat=3
Como alguns sabem estou fazendo um curso de desenvolvimento de games. Neste, brincamos na aula passada de animar um personagem e detectar colisões. Mas parece que o algorítimo da aula passada para detectar colisões está com algum erro.
Estou desenvolvendo nas horas vagas, para treinar C e SDL, o SDLSoccer, que atualmente está mais para WarSoccer :-) . Num próximo post conto a história deste projeto para vocês. Mas o importante é que eu estava tentando utilizar a função para impedir que os jogadores entrem um dentro do outro, dando um efeito meio ‘fantasma’. Mas com a rotina de colisão que estava usando, nada dava certo. E depois de muito depurar, cheguei a conclusão que o erro tinha que estar nela. Então acabei fazendo um mais simples.
Se detectar colisão em retangulos é relativamente simples, mais simples ainda é detectar quando não ocorre a colisão, que foi a lógica que adotei.
Vamos lá:
Sendo r1 e r2 os retângulos 1 e 2 podemos afirmar que não haverá colisão de r1 estiver todo a direita ou todo a esquerda de r2. Ou seja se r1.x+r1.w<r2.x ou r1.x>r2.x+r2.w conforme mostra o diagrama abaixo:
http://blog.renatolouro.com/wp-content/uploads/2006/11/colide1.JPG
Caso contrário, ainda podemos afirmar não haverá colisão se r1 estiver totalmente acima ou totalmente abaixo de r2. Ou seja se r1.y+r1.h<r2.y ou r1.y>r2.y+r2.h conforme mostra o diagrama abaixo:
http://blog.renatolouro.com/wp-content/uploads/2006/11/colide2.JPG
Caso contrário, se r1 não está nem totalmente acima ou totalmente abaixo ou totalmente a direita ou ainda a esquerda, então afirmamos que existe colisão!
Com isso o código que era:
bool colidiu(SDL_Rect r1, SDL_Rect r2)
{
if ((r1.x >= r2.x && r1.x <= (r2.x + r2.w) &&
r1.y >= r2.y && r1.y <= (r2.y + r2.h)) ||
((r1.x + r1.w) >= r2.x && (r1.x + r1.w) <= (r2.x + r2.w) &&
(r1.y + r1.h) >= r2.y && (r1.y + r1.h) <= (r2.y + r2.h)))
return true;
}
Transformamos em algo mais simples e, no mínimo, mais legível:
bool colidiu(SDL_Rect r1, SDL_Rect r2)
{
if(r1.x+r1.w<r2.x || r1.x>r2.x+r2.w) return false;
if(r1.y+r1.h<r2.y || r1.y>r2.y+r2.h) return false;
return true;
}
ou ainda, numa forma ainda mais simples:
bool colidiu(SDL_Rect r1, SDL_Rect r2)
{
if((r1.x+r1.w<r2.x || r1.x>r2.x+r2.w) || (r1.y+r1.h<r2.y || r1.y>r2.y+r2.h)) return false;
return true;
}
Abraços!