Envie Artigos e Concorra a Prêmios
 
Artigos
Article List
Colisao BoundingBox com XNA
Utilizando a Estrutura BoundingBox provida pelo XNA FrameWork
Enviado por Luciano José em 7/1/2008 12:26:20

A estrutura BoundingBox define um volume 3D ocupado por uma caixa. Essa estrutura é alinhada por eixos, sendo assim, cada face da caixa é perpendicular ao eixo x, eixo y ou eixo z. Essa caixa possui 8 vertices. 

Cada ponto preto indica um vertice 

 

Existem vários benefícios no uso de BoundingBox para detecção de colisão. 

  • Uma BoundingBox ajusta formas retangulares alinhadas com os eixos muito bem. Comparada com uma BoundingSphere, uma BoundingBox oferece um ajuste muito maior a objetos retangulares não rotacionados.
  • Devido ao fato das caixas delimitadoras serem alinhadas por eixo, você pode assegurar a suposição de que o resultado obtido na checagem de colisão entre duas caixas delimitadoras é mais rápida do que entre caixas que possam ser rotacionadas.

Desvantagens no uso de uma BoundingBox para detecção de colisão:

  • Quando se rotaciona uma caixa delimitadora, ela não permanece mais alinhada com os eixos, dai será necessario alterar os seus campos Min e/ou Max para a BoundingBox conter totalmente o objeto em questão.
  • Se o modelo sendo delimitado não é alinhado aos eixos, a BoundingBox terá alguns espaços vazios. A quantidade de espaço vazio será maior quando o objeto é rotacionado 45º em relação ao eixo.
  • Espaço vazio na BoundingBox pode resultar em falsos resultados de checagem de colisão.

 

Observe esse boneco alocado na BoundingBox

O boneco foi rotacionado, logo será necessario redefinir os pontos da BoundingBox

Campos públicos de uma Estrutura BoundingBox:

  • public constint CornerCount
  • public Vector3 Max
  • public Vector3 Min
 
CornerCount – informa a quantidade de vertices da estrutura, o valor a ser informado será 8.
Max – O ponto máximo é o ponto com componentes(x, y, z) que são maiores ou iguais às componentes de todos os outros ponto que compõe uma BoundingBox. Visto que uma BoundingBox é alinhado com o eixo, o ponto máximo é o vértice mais acima à direita da face frontal da BoundingBox quando olhada para ela da direção positiva do eixo z.
 

Min – O ponto minimo é o ponto com components(x, y, z) que sao menores ou iguais às componentes de todos os outros pontos da BoundingBox. Visto que uma BoundingBox é alinhada por eixo, o ponto mínimo é o vértice mais a baixo à esquerda da face de trás da BoundingBox quando olhada para ela da direção positiva do eixo z.

 

A definicao do ponto Minimo e Maximo pode variar dependendo de onde a origem esteja definida.

A definição desses pontos(Min e Max), aplicadas acima na foto, é funcionável para a Origem das coordenadas 2D que por padrao no XNA, fica no canto mais a esquerda no canto da tela.

A definição dos pontos Min e Max depende inteiramente de como a sua projeção da tela está definida.

Observação.: Uma BoundingBox é composta por 8 vertices, entretanto, não é necessário definir os 8 vertices. O XNA FrameWork provê isso, sendo necessário apenas informar o ponto mínimo e máximo da BoundingBox, daí será criada uma caixa, alinhada com os eixos.

 

Método Intersects e Contains 

O método Intersects provê completa interação com as outras estruturas da família Bounding Volume e Non-Bounding Volume. Esse método promove teste de intersecção.
 

Bounding Volume

  • BoundingBox
  • BoundingFrustum
  • BoundingSphere
 
Quando o método Intersects interagi com essa família de estruturas, ele retorna true quando há intersecção e false quando não há.
 
Non-Bounding Volume
  • Ray
  • Plane 
 
Assim como as outras estruturas da família Bounding Volume, a estrutura BoundingBox possui um método Contains. Esse método verifica se outro Bounding Volume ou um ponto(Vector3), por exemplo, sobrepõe a BoundingBox. 
O retorno do método Contains é uma enumeração denominada ContainmentType.
Essa enumeração especifica de que forma a estrutura em questão(BoundingBox) contém ou intersecta o outro Bounding Volume. 

Os valores dessa enumeração:

  • Contains
  • Disjoint
  • Intersects

Contains – Indica que um Bounding Volume contém completamente outro Bounding Volume.

 

BoundingBox atribuida ao Box2 está contida no BoundingBox atribuida ao Box1

 

Disjointindica que nao existe sobreposição entre os Bounding Volumes.

BoundingBox atribuida ao Box2 nao está contida, nem tao pouco intersectando a BoundingBox atribuida ao Box1

Intersectsindica que os Bounding Volumes sobrepõe-se parcialmente


Nas 2 fotos acima, a BoundingBox atribuida ao Box2

está intersectando parcialmente a BoundingBox atribuida ao Box1.

 

 
Fonte consultada(Collision Detection Overview):

http://msdn2.microsoft.com/en-us/library/bb313876.aspx 

 


 

Importancia no Uso de BoundingBox em ambientes 2D

 

Se você vai desenvolver algum jogo em 2D, Por que usar BoundingBox ao invés
de usar os metodos Intersects e Contains do Rectangle atribuido ao Sprite do seu jogo?

 

  • O metodo Contains do Rectangle é limitado apenas ao retorno de true ou false, Enquanto o BoundingBox proporciona maior nivel de detalhamento em relação ao seu retorno de método.
  • O XNA FrameWork provê total interação com todos os Bounding Volumes e Non-Bounding Volumes.  
  • Se você quer utilizar Rectangle, para teste de intersecção entre um raio, uma esfera, por exemplo, será necessario vários calculos sofisticados para obter o resultado de intersecção desejado. 
  • Se uma BoundingBox é utilzada para testes de intersecções, mesmo em um ambiente 2D, caso você queira futuramente migrar o jogo para 3D, você terá menor trabalho de migração, já que o Rectangle deixa o jogo limitado ao ambiente de 2D puro.
  •  O FrameWork do XNA já provê “por debaixo dos panos” calculos sofistifcados para testes de intersecção entre as estruturas Bounding Volume e Non-Bounding Volume, basta saber como utilizar as esrtuturas e seus respectivos metodos.

 

 


 

Criando um Prototipo:

O prototipo funciona da seguinte maneira:

A Box1 ficará fixa na tela, e a Box2 será guiada pelo Mouse, quando ocorrer colisao, a Box2 será tingida.

As imagens obtidas desse prototipo sao semelhantes as que foram apresentadas

na enumeração ContainmentType.

Código: 

public class Game1 : Microsoft.Xna.Framework.Game
{
      GraphicsDeviceManager graphics;
      SpriteBatch spriteBatch;
 
        #region Box1
      
      Texture2D box1;
 
      ///
      /// Posicao do Box1
      ///
      Vector2 box1Position;
 
      ///
      /// BoundingBox atribuiada ao Box1
      ///
      BoundingBox boundingBox1;
 
        #endregion
 
        #region Box2
 
      Texture2D box2;
 
      ///
      /// Posicao do Box2
      ///
      Vector2 box2Position;
 
      
      ///
      /// BoundingBox atribuida ao Box2
      ///
      BoundingBox boundingBox2;
 
      ///
      /// Cor de tingimento do Box2.
      /// Evita If´s dentro do metodo Draw,
      /// a mudanca de cor do Box2, sera informada no metodo Update
      ///

      Color box2Color;

        #endregion

...

protected override void Initialize()
{     
 
          //Posicao do Box1, ele ficara parado na tela
          this.box1Position = new Vector2(250, 200);
 
          this.boundingBox1 = new BoundingBox();
 
          /*A definicao da posicao do Box2, será feito na metodo Upadate, já que
             * o Box2 será guiado pelo Mouse
           * */
          
          this.box2Position = new Vector2();
 
          this.boundingBox2 = new BoundingBox();        
 
          base.Initialize();

}

,,,

protected override void Update(GameTime gameTime)
{
          MouseState ms = Mouse.GetState();
 
            #region Box1
          /*Como a Caixa 1, ficará parada, nao é necesario
             * a mudança de seus campos Min e Max. O motivo pelo qual
             * a atualização de seus campos Min e Max está sendo efetuada
             * no metodo Update, é puramente didatica e caso você deseje realizar
             * mais algum teste movimentando o Box1, provalvemente,
             * nada será modificado aqui, bastando apenas modificar
           * a posicao do Box1
             * */         
          this.boundingBox1.Min = new Vector3(this.box1Position, 0);
 
          this.boundingBox1.Max =
              new Vector3(new Vector2(this.box1Position.X + this.box1.Width,
              this.box1Position.Y + this.box1.Height)
              , 0);
 
            #endregion
 
            #region Box2
          
          //O Box2 sera guiado pelo Mouse
          this.box2Position = new Vector2(ms.X, ms.Y);
 
          //Nao é necessário recriar a BoundingBox, é necessario apenas
          //redifinir o Ponto Min e Max
 
          /*Redefinindo o ponto minimo, o menor ponto da face de trás da caixa           
           */
           
          this.boundingBox2.Min = new Vector3(this.box2Position, 0);
 
          /* Redefinindo o ponto Maximo da BoundingBox; o maior ponto da face frontal
           * da caixa
             * */         
          this.boundingBox2.Max =
              new Vector3(new Vector2(this.box2Position.X + this.box2.Width,
              this.box2Position.Y + this.box2.Height)
              , 0);
 
          /*Essas redifinições do ponto maximo e minimo sao necessarias, já que
             * o sprite da caixa se movimentará e a BoundingBox nao sabe que
             * aquilo que estava contido nela, saiu de suas delimitações; é tarefa do
            * programador fazer esse tipo de tratamento
           * */
          
            #endregion
 
            #region Metodo Intersects
 
          if (boundingBox1.Intersects(this.boundingBox2))
          {
              //O Metodo Intersects retornou true, logo, houve colisao
              this.box2Color = Color.Red;
            }
          else
            {
              //O Metodo Intersects retornou false, logo, nao houve colisao
              this.box2Color = Color.White;
            }
 
            #endregion
 
          /*Para testar o comportamento do Metodo Contains, comente todo o
             * bloco de teste do metodo Intersects acima e retire o comentario
             * do bloco de teste do metodo Contains
             * */
 
          /*           
            #region Metodo Contains          
          
            if (boundingBox1.Contains(this.boundingBox2) == ContainmentType.Contains)
            {
                this.box2Color = Color.Yellow;
            }
            else if (boundingBox1.Contains(this.boundingBox2) == ContainmentType.Disjoint)
            {
                this.box2Color = Color.White;
            }
            else if (boundingBox1.Contains(this.boundingBox2) == ContainmentType.Intersects)
            {
                this.box2Color = Color.Red;
            }            
          
            #endregion           
            */
 
          base.Update(gameTime);

}

...

Projeto para Download:  boundingboxcollision.zip 55714 bytes  


Sugestoes, Dúvidas e críticas, como sempre, ajudam muito.

Obrigado!


Sobre o Autor

???
Não Definido
Não Definido
Ocorreu um erro.
Ocorreu um erro.


Clique para avaliar:

Comentários

Adicione seu Comentário
juegos gratis
PrêmiosMinimizar

Envie um artigo para o Sharpgames, colabore com a comunidade e fique famoso! Clique aqui e saiba mais.

Logos do XBox 360, XNA e Games For Windows
Copyright 2010 por SharpgamesPolítica de Privacidade  |  Termos de Uso