Colisão sem bater cabeça

Hoje veremos algumas técnicas básicas, e comumente utilizadas, para detecção de colisão no Flash.

Este artigo é voltado para os iniciantes em programação AS que estão desenvolvendo seus primeiros jogos, e muitos se deparam com o mesmos problema que deparei há não muito tempo atrás, como alguém que também iniciou estudos nessa área recentemente. Espero que esse material seja de utilidade para os interessados.

Estão disponibilizados os arquivos de exemplo no link abaixo, para que possam acompanhar o artigo.

http://rapidshare.de/files/38219238/colisao.zip.html

1- Bounding Boxes - bbox.fla
O meio mais simples de testar uma colisão, é através do método hitTest, também conhecido como colisão entre boxes (caixas).

Esse método checa as extremidades(bounds) de cada um dos objetos, traçando um quadrado que o envolva como um todo (box), e então através de geometria verifica se estes quadrados se sobrepõem.

A utilização de bounding boxes é de certa forma restrita a quadriláteros ou objetos menores onde imperfeiçoes de colisão não seriam notadas.
2- Raio - raio.fla
Técnica similar a dos BoundingBoxes, porém ao invés de quadrados, é testada a sobreposição entre 2 círculos para identificar a colisão

O Flash não possui um método próprio para colisão entre 2 objetos através de raio, porém o processo é bem simples:

distancia = Math.sqrt ( (obj2.x - obj1.x)*(obj2.x - obj1x) + (obj2.y - obj1.y)*(obj2.y - obj1.y) )

if(distancia < obj1.raio + obj2.raio){
//colisão confirmada
}else{
//não há colisão
}

3- Ponto e bound - bound.fla
Nesse tipo de colisão se determina uma extremidade em um eixo, e testa se a posição de um ponto perante a linha imaginária traçada em perpendicular ao eixo que foi determinada essa extremidade.

Esse tipo de colisão pode ser utilizada em vários casos, num game estilo Space Invaders por exemplo, pode ser utilizada para limitar o deslocamento horizontal da nave, já num game sidescroller, essa técnica pode ser utilizada para definir um chão para os objetos.

No arquivo de exemplo apliquei esta técnica 2 vezes, sendo a primeira para determinar a penetração da faca na “parede”, e a segunda para limitar a movimentação da mesma ao comprimento da lâmina.

Note que a “parede” é apenas uma linha, sem nenhum tipo de ligação com o código, mover essa linha no palco exigirá que se reestabeleça o valor “paredeX” para que se mantenha o efeito correto.
4- Ponto e objeto - pontoObj.fla
O método ponto-objeto toma como referência o bounding box do objeto que chama o método, mais o ponto formato pelas coordenadas X e Y passadas como parâmetro, e identifica se este ponto está dentro ou fora do quadrado formado pela box do objeto.

O grande diferencial desse método, é um terceiro parâmetro booleano que permite que utilizemos-nos de ShapeFlag, permitindo um teste de colisão ponto-objeto preciso para objetos complexos.
A primeira vista, um método de colisão preciso, mas que se utiliza apenas de um ponto pode parecer algo meio inútil, mas se avaliarmos as possibilidades possíveis ao utilizar se de vários pontos para o teste de colisão entre 2 objetos, essa técnica pode resolver diversos problemas de colisão.
5- Setor Angular - setorAngular.fla
Aqui utilizamos da mesma técnica do exemplo de Raio, porém, adicionar uma outra condicional, testando o angulo do objeto “flutuante” em relação ao a centro do objeto que gera o setor do angular.

A novidade aqui é o método Math.atan2(), que ao receber as coordenadas de um ponto, retorna seu angulo, no caso nós subtraimos o (x,y) do mouse pelo (x,y) da lanterna, para que essa seja utilizada como centro e referencia para calculo de angulo.
O miolo do código de colisão é esse:

if(dist < raioSetorAngular){
if(Math.abs(anguloObjeto) < anguloSetorAngular/2){
//colisao detectada
}else{
//não há colisão
}
}

Por hoje é só, citei aqui alguns dos métodos mais comuns e efetivos de se testar colisão, e é claro, ainda existem as diversas formas de se resolvê-las, mas isso daria assunto para muitos outros artigos.

[]’s e até a próxima.

4 Responses to “Colisão sem bater cabeça”

  1. Vinicius Says:

    oia…mto legal esse tutorialzinho de colisões existentes, acho q pegando o conceito de cada um dá até p/ conseguir fzer em outras plataformas, e assim vai, mto bom cara, só faltou 2 exemplos codificados mas nd demais…
    abraços.

  2. sam123 Says:

    Uma melhora no métodos dos raios seria em vez de calcular calcular uma raíz quadrada para calcular a distancia, que não é uma função muita rápida, é melhor comparar o quadrado da distancia com a soma de raios ao quadrado.

  3. Artur Corrêa Says:

    Muito legal.
    Uma otimização pode ser feita no caso de colisões por esferas ou círculos: Podemos evitar fazer a operação de raiz quadrada ( que pode ser lenta em algumas plataformas )da seguinte maneira:

    Duas esferas de respectivos raiso a e b colidiram se:

    (a + b)^2 <=((obj2.x - obj1.x)^2+(obj2.y - obj1.y)^2 )^2

  4. Artur Corrêa Says:

    ops ! É claro , não tem que elevar o segundo termo ao quadrado .
    o certo é :

    Duas esferas de respectivos raiso a e b colidiram se:

    (a + b)^2 <=((obj2.x - obj1.x)^2+(obj2.y - obj1.y)^2 )

Leave a Reply