| |
27 - Detectando colisões
O Ato de detectar colisões entre desenhos é muito importante para qualquer tipo de jogo.
Em um jogo como o Super Mario por exemplo, não podemos sair da tela, nem podemos tocar do lado dos inimigos.
Para isso foi programado uma detecção de colisão, que na verdade é uma formula bem simples.
Todo objeto na tela deve ter uma posição X e Y definida, desta forma,
podemos saber se o X e Y de um objeto está dentro da área do X e Y de outro objeto.
Primeiro, vamos fazer a colisão de um objeto com a tela.
Sabemos que no Allegro, a posição 0,0 é o limite esquerdo e do topo.
Usaremos uma variável da Allegro para saber qual é o tamanho máximo da tela para pegar-mos o X e Y do limite direito e final da tela.
FÓRMULA
- A posição X do objeto não pode ser menor que zero
- A posição de X + o tamanho do objeto ( em X ) não pode ser maior que o limite da tela. Se for maior, o objeto vai sair da tela.
- A posição Y do objeto não pode ser menor que zero
- A posição de Y + o tamanho do objeto ( em Y ) não pode ser maior que o limite da tela. Se for maior, o objeto vai sair da tela.
Tome cuidado quando o objeto tiver um tamanho X diferente do tamanho Y
|
|
CÓDIGO...
// Colisão com os cantos da tela
#include <allegro.h>
int main()
{
allegro_init();
set_color_depth(16);
install_keyboard();
set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 640, 480, 0, 0);
// inicio da programação atual
int x = 0;
int y = 0;
// dimensao do quadrado
// variáveis constantes nunca mudam durante a execução do programa
const int tamanho = 100;
// Laço principal
while( !key[KEY_ESC] )
{
if ( key[KEY_UP] )
{
y--;
}
if ( key[KEY_DOWN] )
{
y++;
}
if ( key[KEY_LEFT] )
{
x--;
}
if ( key[KEY_RIGHT] )
{
x++;
}
// limitando o quadrado dentro da tela
if ( x < 0 )
{
x = 0;
}
if ( (x+tamanho) > SCREEN_W )
{
x = SCREEN_W - tamanho;
}
if ( y < 0 )
{
y = 0;
}
if ( (y+tamanho) > SCREEN_H )
{
y = SCREEN_H - tamanho;
}
// esta função limpa a tela
clear( screen );
// escrevemos um quadrado na tela na posição x e y
rectfill( screen, x, y, x+tamanho, y+tamanho, makecol(255, 0, 0) );
// imprimimos as coordenadas x e y na tela para o usuário ver
textprintf_ex( screen, font, 10, 10, makecol(255,0,0), -1, "Variavel X: %d", x);
textprintf_ex( screen, font, 10, 20, makecol(255,0,0), -1, "Variavel Y: %d", y);
// essa função faz o allegro esperar um pouco antes de voltar para o while
rest(10);
}
allegro_exit();
return 0;
}
END_OF_MAIN();
FIM DE CÓDIGO...
Basicamente:

Imagine que as linhas pretas são os limites da tela.
Temos que, o x de nosso quadrado nunca pode ser menor que o x limite da tela.
Para resolver isso fizemos:
if ( x < 0 )
{
x = 0;
}
O mesmo para o y.
Agora, para testar os limites finais da tela:
Imagine que em x=100 o quadrado já está tocando no final da tela.
Para testar isso, fizemos o seguinte:
if ( (x+tamanho) > SCREEN_W )
{
x = SCREEN_W - tamanho;
}
Se imaginarmos que o SCREEN_W seja de 200, podemos dizer que
x ( 100 ) + tamanho ( 100 ) nunca pode ser maior que o SCREEN_W.
O mesmo acontece para y.
Dica
Fique esperto com estes testes quando o tamanho do objeto for difrente para X e Y.
|
|
Agora vamos inserir um quadrado no meio da tela, e vamos fazer um teste de colisão neste quadrado.
CÓDIGO...
// Colisão com os cantos da tela
#include <allegro.h>
int main()
{
allegro_init();
set_color_depth(16);
install_keyboard();
set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 640, 480, 0, 0);
// inicio da programação atual
int x = 0;
int y = 0;
const int tamanho = 50;
const int obj_tam = 100;
const int obj_x = ( SCREEN_W - (obj_tam / 2) ) / 2;
const int obj_y = ( SCREEN_H - (obj_tam / 2) ) / 2;
bool colide = false;
// Criando BUFFER para double buffer
BITMAP *buffer = NULL;
buffer = create_bitmap(800,800);
// Laço principal
while( !key[KEY_ESC] )
{
if ( colide == false )
{
if ( key[KEY_UP] )
{
y--;
}
if ( key[KEY_DOWN] )
{
y++;
}
if ( key[KEY_LEFT] )
{
x--;
}
if ( key[KEY_RIGHT] )
{
x++;
}
}
// limpa o nosso novo buffer
clear( buffer );
// escreve o quadrado no buffer
rectfill( buffer, x, y, x+tamanho, y+tamanho, makecol(255, 0, 0) );
rectfill( buffer, obj_x, obj_y, obj_x+obj_tam, obj_y+obj_tam, makecol(0, 0, 255) );
// imprimimos as coordenadas x e y na tela para o usuário ver no buffer
textprintf_ex( buffer, font, 10, 10, makecol(255,0,0), -1, "Variavel X: %d", x);
textprintf_ex( buffer, font, 10, 20, makecol(255,0,0), -1, "Variavel Y: %d", y);
textprintf_ex( buffer, font, 10, 30, makecol(255,0,0), -1, "obj X: %d", obj_x);
textprintf_ex( buffer, font, 10, 40, makecol(255,0,0), -1, "obj Y: %d", obj_y);
// verifica se colide
if ( (x+tamanho) >= obj_x && x <= obj_x+obj_tam )
{
if ( (y+tamanho) >= obj_y && y <= obj_y+obj_tam )
{
textout_ex(buffer, font, "COLIDE", obj_x+25, obj_y+50, makecol(0, 255, 0), -1);
}
}
// imprime o buffer na tela
vsync();
blit(buffer, screen, 0,0,0,0, SCREEN_W, SCREEN_H);
// essa função faz o allegro esperar um pouco antes de voltar para o while
rest(10);
}
allegro_exit();
return 0;
}
END_OF_MAIN();
FIM DE CÓDIGO...
Primeiro exemplo:
Neste caso, a imagem vermelha está fora dos limites da imagem do centro azul.

Neste caso, temos o vermelho dentro do limite X da imagem azul, porém, o vermelho continua fora do limite Y, logo, ainda não temos uma colisão.
Já temos este teste:
if ( (x+tamanho) >= obj_x && x <= obj_x+obj_tam )

Neste caso, temos o vermelho dentro do limite Y da imagem azul, porém, o vermelho continua fora do limite X, logo, ainda não temos uma colisão.
Neste caso, já temos este teste:
if ( (y+tamanho) >= obj_y && y <= obj_y+obj_tam )

E no último exemplo, temos a colisão em X e Y dentro dos limites nas imagem azul.
Juntando os 2 testes, temos:
// verifica se colide
if ( (x+tamanho) >= obj_x && x <= obj_x+obj_tam )
{
if ( (y+tamanho) >= obj_y && y <= obj_y+obj_tam )
{
textout_ex(buffer, font, "COLIDE", obj_x+25, obj_y+50, makecol(0, 255, 0), -1);
}
}
Contribuidor
Adriano Waltrick
01/08/2007
|
|