Artigo no estilo: Curso
Por que eu devo ler este artigo:Este artigo é útil por explorar os principais conceitos na prática acerca da biblioteca de desenvolvimento de gráficos 2D Pixi.js. Essa biblioteca ficou famosa por sua capacidade de abstrair o WebGL (padrão baseado no OpenGL ES 2.0 que fornece interfaces de programação de gráficos em 3D) de forma rápida e extremamente leve em comparação com outras ferramentas do tipo. O leitor aprenderá a implementar um mecanismo próprio e robusto de detecção de colisões entre objetos no jogo e, sobretudo, a como executar ações quando elas ocorrerem. Esse trabalho se dará através da biblioteca utilitária do Bump.js, que fornece uma linha de execução pronta para detectar as colisões. Veremos tudo isso através da construção de um jogo simples de caça à tocha em um cenário repleto de personagens inimigos, com barra de vida e cenas de game over e sucesso.

O Pixi.js é um framework muito robusto que atende à grande maioria das implementações que você venha a precisar no desenvolvimento dos seus jogos ou aplicações gráficas na web. Entretanto, muitos dos recursos precisam fazer uso de APIs de terceiros e/ou bibliotecas utilitárias para atender a implementações não fornecidas pelo mesmo, como o mecanismo de detecção de colisões entre objetos nos jogos. Esse tipo de funcionalidade é extremamente importante, principalmente em jogos clássicos que seguem o estilo de personagem principal contra personagens inimigos. Além disso, mesmo que não tenhamos o choque entre personagens ao longo do jogo, o mínimo de detecção de espaço entre os limites do cenário e o personagem nele inserido precisa ser atendido pelo seu projeto.

E é justamente sobre isso que iremos tratar neste artigo: como detectar a colisão entre dois objetos e, a partir disso, determinar o que acontecerá com os mesmos e com o cenário como um todo. É importante salientar que esse recurso precisa ser o mais genérico possível, retornando sempre um booleano e recebendo os objetos que necessitam ser checados quanto à colisão; uma vez que só determinaremos a ação pós-colisão quando a mesma ocorrer. O leitor precisa, a este ponto, entender que os conceitos aprendidos até aqui se intercalam e comunicam entre si, tendo dependência direta e hierárquica. Por exemplo, para que possamos criar uma função que detecte uma colisão, precisamos antes criar os objetos de sprite via Texture Packer e JSON, bem como mapear seus eventos de clique nas teclas que resultarão na sua movimentação básica, etc. Portanto, uma boa revisão nos conceitos vistos seria muito aconselhada.

Detectando colisões

Agora que já temos a estrutura básica necessária para trabalhar, em JSON, com a criação dinâmica de sprites adicionando-os ao cenário, podemos partir para uma técnica muito importante no universo dos games: a detecção de colisões entre os objetos. Até o momento, nossos objetos apenas desempenham tarefas simples, como a caminhada (ou corrida, na qual incluímos os conceitos de velocidade, aceleração e fricção) e os eventos de movimento associados às teclas das setas do seu teclado.

O Pixi.js não fornece, por padrão, um mecanismo nativo de detecção de colisões, mas podemos fazer uso da biblioteca chamada Bump.js (vide seção Links), que já se integra automaticamente ao Pixi, disponibilizando uma série de funções para lidar com a manipulação de colisões em jogos 2D.

Como primeiro passo, vamos efetuar o download da biblioteca (apenas do arquivo bump.js) e importar o mesmo na nossa página HTML logo abaixo do script do Pixi (é interessante considerar a criação de um novo arquivo para o código que faremos a seguir). Finalmente, para fazer uso da API, basta criar um novo objeto do tipo Bump na sua função setup(), tal como:

var bump = new Bump(PIXI);

Veja que também passamos o objeto PIXI como parâmetro, já que a mesma precisa receber a engine de jogos que estamos usando.

O que vamos usar da API em si basicamente é o seu método principal: a função hitTestRectangle() (acesse o arquivo JavaScript para mais detalhes da sua implementação). Essa função, por sua vez, recebe dois parâmetros: os dois sprites a serem comparados; e retorna um booleano informando se há alguma colisão entre ambos. Assim, podemos usá-la em estruturas condicionais para atestar se houve ou não alguma colisão naquele momento. Na maioria dos casos, a checagem de colisão deve ser feita em todos os frames do jogo, portanto é necessário incluir tal lógica dentro da função play() que será chamada a cada FPM.

Prática de jogo: Em busca da tocha!

Com o intuito de assimilar a ideia da detecção de colisão e unir a mesma aos conceitos vistos até aqui, faremos um jogo completo e bem simples, cujo nome será “Em busca da tocha!”. Teremos um player central, um garoto, que terá por objetivo buscar uma tocha dentro do cenário que estará cercado por inimigos representados pelos personagens de fantasmas. Também exibiremos uma barra de vida no topo do cenário na cor verde, que decrescerá a medida que o personagem principal for atingido por algum dos fantasmas. Se ele for atingido o suficiente para zerar a barra, o jogo encerrará e o jogador será redirecionado para a tela de game over. Caso contrário, ele terá de levar a tocha até a porta de saída do cenário, no canto superior esquerdo, aí sim o jogador será bem-sucedido e ganhará o jogo e então poderemos direcioná-lo para a tela de sucesso.

Também implementaremos a detecção de colisão com as bordas do cenário, impossibilitando o jogador de ir além das paredes. E, para completar o jogo, criaremos um texto com o título do jogo e um contador regressivo antes do jogo começar para preparar o jogador, limpando os referidos objetos assim que o contador chegar em zero.

Para iniciar, crie um novo arquivo HTML (chamaremos aqui de cacatocha.html) e inicialize-o com a estrutura de HTML e imports demonstrados na Listagem 1. A mesma já nos é conhecida dos exemplos anteriores.

Listagem 1. Estrutura inicial da página cacatocha.html.


  01 <!doctype html>
  02 <meta charset="utf-8">
  03 <title>Caça à Tocha!</title>
  04 <style type='text/css'>
  05     * {
  06         padding: 0;
  07         margin: 0
  08     }
  09     
  10     @font-face {
  11         font-family: 'Pipe Dream';
  12         src: url('font/Pipe_Dream.ttf') format('truetype');
  13         font-weight: normal;
  14         font-style: normal;
  15     }
  16 </style>
  17 
  18 <body>
  19     <script src="js/pixi.min.js"></script>
  20     <scr ... 

Quer ler esse conteúdo completo? Tenha acesso completo