Artigo no estilo: Curso

Por que eu devo ler este artigo:Este artigo tem como objetivo mostrar de forma prática e direta os conhecimentos e técnicas mais utilizados no desenvolvimento de jogos usando HTML5 em conjunto com Canvas e JavaScript.

O mesmo se propõe a explorar os recursos da tecnologia, bem como as boas práticas da comunidade, através do desenvolvimento de um jogo estilo shoot ‘em up, onde os personagens se atacam no plano horizontal com combos, contagem de pontos e reinicialização do mesmo.

Desta forma, o desenvolvedor poderá usar conceitos como otimização de performance, reaproveitamento de objetos, orientação a objetos, herança e programação multicamada dentro de um cenário real, otimizando seu nível de conhecimento e, consequentemente, sua produtividade.

Atualmente, uma imensa maioria das aplicações que encontramos nas lojas da Play e App Store correspondem a aplicativos desenvolvidos usando somente HTML5 e JavaScript. Essa ampla adoção de duas tecnologias deveras comuns se deve às cada vez mais frequentes adoções por parte dos desenvolvedores de frameworks multiplataforma como o Cordova, PhoneGap, etc. que usam a tecnologia HTML5 como base e simplificam, consideravelmente, a criação e manutenção de aplicativos móveis e distribuídos.

Aliada a tais fatores, encontra-se também uma preferência exponencial por aplicações que visam o entretenimento, como jogos, players e derivados. E quando se trata de jogos, as estatísticas mostram que os desenvolvidos sob a ótica 2D (bidimensionais), que em sua grande maioria são bem mais simplistas e diretos, ganham a preferência dos usuários em disparado.

Ao mesmo tempo, do ponto de vista técnico, eles também são mais simples de desenvolver em comparação aos jogos 3D, o que acaba criando uma gama maior de possibilidades para as empresas.

Para possibilitar maior flexibilidade e rapidez no desenvolvimento de jogos para esse público, as empresas, por sua vez, optam cada vez mais pela HTML5 como opção barata, fácil de utilizar e que consome menos recursos em se tratando de ferramentas, softwares proprietários e/ou de terceiros, bem como por sua desnecessidade de ambientes complexos e uso de mais de uma linguagem de programação.

Tudo isso é possível através do recurso que a tecnologia apresenta chamado Canvas, que são elementos da HTML5 que possibilitam a “pintura” de todos os tipos de gráficos, desde simples linhas até gráficos mais complexos, tendo como base a linguagem JavaScript.

Neste artigo, nós aprenderemos os recursos do Canvas e como ele se integra ao trio HTML5, CSS e JavaScript através da criação de um jogo no estilo shoot ‘em up, um gênero de jogos para computador em que o personagem principal se concentra em atirar nos alvos (inimigos) em cenários horizontais, de modo que outros aspectos do jogo são simplificados para facilitar tudo isso. No mesmo jogo, também criaremos pontuações, a possibilidade de reiniciar a partida caso o player seja atingido, um botão para silenciar a música de fundo, assim como a geração de cenários e players de forma randômica, para deixar o jogo mais interessante.

Os personagens serão baseados em um jogo de guerra, com soldados futuristas contra os monstros espaciais que invadiram a terra.

Para controlar o player serão usadas as teclas de navegação do teclado (←↑↓→), que permitirão mover o mesmo por toda a tela, dentro do perímetro máximo que determinarmos para ele (vamos criar uma barreira invisível para que o player não chegue muito perto dos inimigos, e vice-versa); e para atirar será usada a tecla de barra de espaço do teclado.

O jogo irá rodar enquanto o jogador não morrer, e o placar será incrementado sem fim, consequentemente; até que o mesmo seja atingido por um dos inimigos (que também virão infinitamente). Neste jogo, não implementaremos recursos como vidas, pausa ou aumento da dificuldade com o tempo, mas são recursos que o leitor estará apto a desenvolver após este artigo.

O ambiente para desenvolvimento é bem simples, basta ter um editor de texto e um navegador web de sua preferência. É recomendável usar algum editor que reconheça arquivos de extensões .html e.js, como o Notepad++ (vide seção Links). Mas antes de começarmos a implementação de fato, vamos entender melhor o que são Canvas e como eles funcionam.

Canvas

A HTML5 disponibiliza em sua lista de tags básicas, a tag <canvas>. Através dela, os desenvolvedores front-end tem em mãos um poderoso recurso para desenhar grafos, gráficos de jogos ou outras imagens visuais em tempo real, usando apenas JavaScript.

É comum vermos vários plug-ins jQuery ou JavaScript fazendo uso de canvas para exibir gráficos de linha, pizza, dentre outras variantes. Em outras palavras, um canvas (ou telas, em tradução livre) é um retângulo na sua página onde você pode usar JavaScript para desenhar qualquer coisa que deseje.

O Canvas foi criado inicialmente pela Apple para ser usado no interior do seu Sistema Operacional, num componente chamado OS X WebKit, em 2004, e trouxe consigo uma gama de novos recursos ao SO. Pouco tempo depois foi patenteado pelo Web Hypertext Application Technology Working Group (WHATWG), e hoje é amplamente usado e padronizado por todos os navegadores mais recentes.

Para garantir que você terá pleno acesso aos recursos do Canvas, é aconselhado usar a versão mais recente do seu browser, uma vez que versões mais antigas não o proveem em suas implementações padrão. Veja na Figura 1 a lista de browsers que suportam o Canvas, com suas respectivas versões e S.O.s.

Criando um jogo 2D com Canvas

Figura 1. Lista de navegadores web que suportam o Canvas.

Conforme observado, o Internet Explorer só provê suporte nativo ao recuso a partir de sua versão 9. Se você desejar habilitar o recurso nas versões 7.0 ou 8.0, existe um projeto chamado explorercanvas (ver seção Links), que foi criado para servir como extensão ao IE nessas versões e simular a funcionalidade do Canvas no navegador, bastando para isso incluir algumas linhas de script nas páginas que o usuário deseja executar.

Além disso, em se tratando de versões de browser para dispositivos móveis, o Canvas já vem como recurso básico nos mesmos. A partir do iPhone 1.0 e Android 1.0 já temos o recurso disponível.

A estrutura HTML de um canvas é relativamente simples e se aproxima muito da que já estamos acostumados em páginas web:

<canvas
id="meuCanvas" width="250" height="250">
Esse texto será exibido caso seu browser não suporte o Canvas
</canvas>

Neste exemplo, estamos fazendo uso apenas de três atributos básicos das tags HTML, como largura, altura e identificação. Mas os demais atributos padrão de tags também podem ser usados e iremos demonstrar outros exemplos ao longo do artigo.

Adicionalmente, é importante termos em mente que desenhar qualquer coisa com canvas em HTML é uma operação pesada, que consome muitos recursos do browser.

Por causa disso, nós precisaremos reduzir a quantidade de “desenhos” que faremos com o canvas para garantir que a performance seja boa o suficiente para não interromper a execução do jogo.

Criando o projeto

Antes de começar a programar efetivamente, vamos criar uma estrutura básica de diretórios para o nosso projeto. Veja na Listagem 1 a estrutura padrão que usaremos para o nosso aplicativo de jogo.

Listagem 1. Estrutura básica de pastas para o projeto

  jogo-guerra-espacial
  --------| imgs
  --------| js
  --------| css

Essa estrutura nos ajudará a não nos perdermos dentre os diferentes tipos de arquivos que manipularemos no projeto.

Agora crie um novo arquivo de extensão .html e o nomeie “index.html”. Esse será o arquivo de conteúdo HTML principal do projeto. Adicione o conteúdo da Listagem 2 ao mesmo.

Listagem 2. Conteúdo da página inicial do jogo

  <!DOCTYPE html>
  <html>
         <head>
               <title>Jogo: Guerra do Espaço</title>
               <style>
                      #planoDeFundo {
                             background: transparent;
                             left: 0px;
                             top: 0px;
                             position: absolute;
                      }
               </style>
         </head>
         <body onload="iniciar()">
               <!-- Esse canvas será usado inicialmente para o plano de fundo do jogo -->
               <canvas id="planoDeFundo" width="948" height="592">
                      Seu navegador não suporta o recurso de Canvas. Por favor, tente novamente com um navegador diferente.
               </canvas>
               <script src="js/global.js"></script>
         </body>
  </html> 

Criamos um elemento canvas e incluímos o texto dentro dele, no caso do navegador não suportar o recurso de canvas. O método iniciar() representará o construtor dos canvas que usaremos e será responsável por carregar todos os recursos iniciais.

A largura e altura do elemento receberam estes valores para que se adéquam ao tamanho das imagens que usaremos posteriormente para representar os cenários do jogo. Por fim, carregamos o arquivo JavaScript que conterá todas as funções de script do jogo como um todo.

Crie, em seguida, um novo arquivo na pasta js do nosso projeto chamado “global.js”, que conterá as funções JavaScript.

Criando os cenários

A partir de agora, vamos trabalhar essencialmente no arquivo de JavaScript. Como o mesmo irá se estender um pouco, vamos nos ater às funções.

Criaremos função por função, que deverão ser adicionadas em sequência no mesmo arquivo, para facilitar o entendimento do código geral. A primeira coisa a se criar é o objeto que será responsável por desenhar coisas no jogo, como mostra a Listagem 3.

Listagem 3. Código da classe Desenhavel

  /**
   * Cria o objeto "Desenhavel" que será a classe base para
   * todos os objetos desenháveis do jogo. Define também as variáveis padrão
   * que todos os objetos filhos herdarão, assim como as funções padrão.
   */
  function Desenhavel() {
         this.velocidade = 0;
         this.larguraCanvas = 0;
         this.alturaCanvas = 0;
         
         // Define uma função abastrata para ser sobrescrita nos objetos filho
         this.desenhar = function() {
         };
         
         this.iniciar = function(x, y) {
               // Variáveis padrão do eixo cartesiano
               this.x = x;
               this.y = y;
         }
  }

O tipo de estrutura que vemos nessa listagem é bem comum em alguns frameworks JavaScript, onde temos a estrutura de uma classe sendo representada, tal como é feita com componentes orientados a objetos.

Neste caso, definimos um escopo de objeto desenhável, com os recursos, atributos e funções mínimos necessários para se pintar na tela algum objeto JavaScript representativo. Quando quisermos criar um objeto de tipo Jogador ou Inimigo, por exemplo, basta que herdemos desta classe e suas características serão, obrigatoriamente, associadas ao novo objeto.

Em termos de programação, o chamamos de objeto abstrato. As vantagens dessa abordagem vão além dos conceitos básicos de herança, atingindo também o polimorfismo e a facilidade na manutenção do código, quando desejarmos alterar estruturas que devam refletir em todos os objetos “desenháveis”, por exemplo.

Podemos observar também que na mesma declaração temos uma função iniciar() sendo declarada também de forma genérica.

Ela será responsável por receber os valores do objeto, estes que serão definidos no modelo de plano cartesiano, com as respectivas coordenadas x e y, referentes à posição onde aquele objeto se encontra dentro do limite de pintura da tela.

Nós também precisaremos salvar a informação referente à velocidade que aquele objeto deve se mover na tela, visto que teremos diferentes velocidades para cada “desenhável” no jogo. Finalmente, criamos a função desenhar() (também genérica), com o intuito de fornecer aos objetos filhos a possibilidade de sobrescrever a forma como os mesmos serão impressos na tela.

Em sequência, criaremos agora um novo objeto repositorio no nosso modeloo. Veja na Listagem 4 o código para tal.

Listagem 4. Objeto de repositório das imagens

  /**
   * Define um objeto para manter todas as nossas imagens do jogo para 
   * evitar que elas sejam criadas mais de uma vez.
   */
  var repositorio = new function() {
         this.planofundo = new Image();
         
         // Configura os caminhos (src) das imagens
         this.planofundo.src = "imgs/pf.png";
  }

Esse código basicamente cria um objeto de domínio, que será responsável por guardar os objetos a serem desenhados na tela (até o momento somente a imagem de plano de fundo). Esse tipo de estratégia serve tanto para não deixar os objetos soltos dentro do código, tendo que criar várias referências para eles, quanto para impedir que o navegador use recursos extra para criar um objeto por vez em várias chamadas distintas.

À medida que formos evoluindo no artigo, esse objeto passará a receber novas entradas, dadas as adições dos demais atores no jogo.

Para que o código funcione, é necessário, obviamente, que as imagens estejam nos lugares definidos. Para isso, baixe as mesmas diretamente do link de download de fonte deste artigo e posicione-as corretamente no seu projeto.

Agora que temos os objetos de template desenhável e o repositório de imagens, vamos lidar com a implementação do plano de fundo do cenário. Adicione o código contido na Listagem 5 ao seu arquivo js.

Listagem 5. Função que cria e anima o plano de fundo

  /**
   * Cria o objeto PlanoFundo que se tornará um filho do
   * objeto Desenhavel. O plano de fundo será desenhado nesse objeto
   * e criará a ilusão de movimento ao deslocar a imagem.
   */
  function PlanoFundo() {
         this.velocidade = 1; // Redefine a velocidade do plano de fundo para pintura
         
         // Implementa a função abstrata
         this.desenhar = function() {
               // Pinta o plano de fundo
               this.x -= this.velocidade;
               this.context.drawImage(repositorio.planofundo, this.x, this.y);
               
               // Desenha outra imagem na borda superior da primeira imagem
               this.context.drawImage(repositorio.planofundo, this.x + this.larguraCanvas, this.y);
   
               // Se a imagem for deslocada para fora da tela, redefine-a
               if (Math.abs(this.x) >= this.larguraCanvas)
                      this.x = 0;
         };
  }
  // Define o PlanoFundo como herdeiro das propriedades de Desenhavel
  PlanoFundo.prototype = new Desenhavel();

...

Quer ler esse conteúdo completo? Seja um assinante e descubra as vantagens.
  • 473 Cursos
  • 10K Artigos
  • 100 DevCasts
  • 30 Projetos
  • 80 Guias
Tenha acesso completo