Conheça a iniciativa da Biblioteca dos Desenvolvedores  
Índice da Biblioteca  
Área dos Usuários  
Fórum de Discussão  
Forúm
 
 

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);
         }
      }

Download do exemplo 1 - Clique Aqui

Download do exemplo 2 - Clique Aqui

 


Contribuidor
Adriano Waltrick
01/08/2007


 

« Anterior

 

Próximo »

 
 

01/06/2007 (C) Copyright. Todos os Direitos Reservados. Leia a política de privacidade do portal.
É proibida a cópia de conteúdo deste site de acordo com a Lei Brasileira de Direitos Autorais.