Desenvolvimento de Jogos 2D em HTML5: Apresentando o Snail Bait

Introdução ao seu primeiro videogame de plataforma

Nesta série, David Geary, especialista em HTML5, mostra como implementar um videogame 2D HTML5 passo a passo. Esta parte inicial do artigo mostra o jogo finalizado e, em seguida, mostra como começar a implementá-lo do zero. Se você já quis implementar um jogo em HTML5, mas não teve tempo para dominar todos os detalhes, esta série é para você.

David Geary, Author and speaker, Clarity Training, Inc.

David GearyO autor de Core HTML5 Canvas, David Geary, também é cofundador do Grupo de Usuários de HTML5 de Denver e autor de oito livros sobre Java, inclusive os best-sellers sobre Swing e JavaServer Faces. David atua como palestrante em várias conferências, como JavaOne, Devoxx, Strange Loop, NDC e OSCON — e ganhou o prêmio JavaOne Rock Star três vezes. Escreveu a série de artigos sobre JSF 2 fu e GWT fu para o developerWorks. É possível seguir David no Twitter em @davidgeary.



25/Set/2012

O lado bom do desenvolvimento de software é que é possível dar vida na tela a praticamente qualquer coisa que imaginar, dentro de certos limites. Livres das restrições físicas que atrapalham os engenheiros em outras disciplinas, os desenvolvedores de software vêm usando APIs gráficas e kits de ferramentas de UI para implementar aplicativos criativos e convincentes. Talvez a programação de jogos seja o gênero mais criativo do desenvolvimento de software — poucos empreendimentos são mais gratificantes, do ponto de vista criativo, do que transformar em realidade a sua visão em relação a um jogo.

Videogames de plataforma

Donkey Kong, Mario Bros., Sonic the Hedgehog e Braid são jogos bem conhecidos e sucesso de vendas — todos eles são jogos de plataforma. Os jogos de plataforma já foram responsáveis por até um terço das vendas de videogame. Atualmente, a participação deles no mercado é muito mais baixa, mas ainda há jogos de plataforma de sucesso.

Gratificante, no entanto, não significa fácil; na verdade, significa o contrário disso. A implementação de jogos — principalmente de videogames — exige uma compreensão fora do comum sobre programação, um bom conhecimento de gráficos e animação e muita matemática combinada com altas doses de arte e criatividade. E isso é só o começo. Os desenvolvedores de jogos bem-sucedidos passam muito tempo aperfeiçoando as suas criações para refinar a jogabilidade e os gráficos — e também implementando muitos aspectos que não têm nada a ver com a jogabilidade — como quadros de pontuação, instruções, animações entre vidas e níveis e sequências de fim de jogo.

O objetivo desta série é mostrar como implementar um videogame HTML5, para que você possa começar a trabalhar no seu próprio jogo.

Veja a transcrição do vídeo "About this series" aqui.

O jogo: Snail Bait

Nesta série, eu irei mostrar como implementar um videogame de plataforma usando principalmente a API de tela do HTML5. O jogo é Snail Bait, mostrado na Figure 1. É possível jogar online; consulte Recursos para obter um link para o jogo. Certifique-se de que o seu navegador tenha aceleração de hardware para tela (implementada recentemente na maioria dos navegadores, inclusive no Chrome, desde a versão 18); do contrário, o desempenho do Snail Bait será muito ruim. (Consulte a barra lateral Desempenho da tela de HTML5 para obter mais informações.)

Figura 1. Snail Bait executando no Chrome
Snail Bait executando no Chrome

Tecnologias HTML5 usadas no Snail Bait

  • Tela (API 2D)
  • Controle de sincronização para animações baseadas em script
  • Áudio
  • CSS3 (transições e consultas de mídia)

O Snail Bait é um jogo de plataforma clássico. A protagonista, que eu chamarei simplesmente de corredora, corre e pula entre plataformas flutuantes que se movem horizontalmente. O objetivo final da corredora é chegar a uma plataforma pulsante com um botão dourado no final do nível. A corredora, a plataforma pulsante e o botão dourado são mostrados na Figura 1.

O jogador controla a corredora com o teclado: d a move para a esquerda, k a move para a direita j e f são os botões para pular e p pausa o jogo.

Quando o jogo começa, você tem três vidas. Os ícones da corredora, representando o número de vidas restantes, são exibidos acima e à esquerda da tela do jogo, como é possível ver na Figura 1. Na jornada da corredora para chegar ao fim do nível, ela precisa evitar os vilões — abelhas, morcegos e uma lesma — enquanto tenta capturar itens valiosos como moedas, rubis e safiras. Se a corredora se choca com os vilões, ela explode. Você perde uma vida e tem que voltar para o começo do nível. Quando ela se choca com os "heróis", a sua pontuação aumenta e você é recompensado com um efeito sonoro agradável.

WASD?

Por convenção, os jogos de computador costumam usar as teclas w, a, s e d para controlar o jogo. Essa convenção se estabeleceu principalmente porque permite que os jogadores destros usem o mouse e o teclado ao mesmo tempo. Além disso, deixa a mão direita livre para pressionar a barra de espaço ou as teclas modificadoras, como CTRL ou ALT. O Snail Bait não usa o WASD porque não recebe entrada do mouse nem das teclas modificadoras. No entanto, é possível modificar o código do jogo facilmente para usar qualquer combinação de teclas.

Os vilões basicamente ficam esperando a corredora se chocar com eles. Entretanto, a lesma joga bombas periodicamente (a bola prateada que é mostrada perto do centro da Figura 1). As bombas, como os outros vilões, explodem a corredora quando se chocam com ela.

O jogo termina de duas formas: ou você perde todas as três vidas ou chega à plataforma pulsante (com pontos de bônus por aterrissar no botão dourado). De uma forma ou de outra, o jogo termina com os créditos mostrados na Figura 2:

Figura 2. Créditos do jogo
Créditos do jogo

O que não se pode ver na Figura 1 é que tudo — com exceção da corredora, cujo movimento você controla — rola continuamente. Essa rolagem caracteriza o Snail Bait mais especificamente como um jogo de plataforma com rolagem lateral . Entretanto, esse não é o único movimento do jogo — o que me lava aos sprites e seus comportamentos.


Sprites: o elenco de personagens

Desempenho da tela de HTML5

Não faz muito tempo que a maioria dos navegadores implementaram a aceleração de hardware para as transições de CSS, mas ainda não a implementaram para a tela. A tela sempre foi relativamente rápida, principalmente se comparada com outros sistemas gráficos — como o Scalable Vector Graphics (SVG) — mas a tela sem aceleração de hardware não se compara a qualquer sistema com aceleração de hardware.

Agora, todos os navegadores modernos têm aceleração de hardware para tela. O iOS 5 também tem — isso significa que agora é possível fazer videogames baseados em tela com uma animação boa não só no desktop, mas também em dispositivos móveis da Apple.

Com a exceção do plano de fundo, tudo no Snail Bait é um sprite. O sprite é um objeto que pode ser pintado na tela do jogo. Os sprites não fazem parte da API de tela, mas a sua implementação é simples. Os sprites do jogo são:

  • Plataformas (objetos inanimados)
  • Corredora (protagonista)
  • Abelhas e morcegos (vilões)
  • Botões (bons)
  • Rubis e safiras (bons)
  • Moedas (boas)
  • Lesma (ruim)
  • Bombas de lesma (ruins)

Além de rolar da direita para a esquerda, quase todos os sprites do jogo têm seu próprio movimento independente. Por exemplo, os rubis e safiras sobem e descem a velocidades variadas, e os botões e a lesma se movem para frente e para trás ao longo da plataforma onde residem.

Replica Island

A ideia dos comportamentos dos sprites — que são um exemplo do padrão de design Estratégia — vem do Replica Island, um jogo de plataforma bastante conhecido da plataforma Android. A maioria dos gráficos do Snail Bait vem do Replica Island (usados mediante permissão). Consulte Recursos para obter os links para o padrão de design Estratégia na Wikipédia e na página inicial do Replica Island.

Esse movimento independente é um dos vários comportamentos do sprite. Os sprites podem ter outros comportamentos que não têm nada a ver com o movimento; por exemplo, além de subir e descer, os rubis e as safiras brilham.

Cada sprite tem um array de comportamentos. Um comportamento é simplesmente um objeto com um método execute() . Em todos os quadros de animação, o jogo chama o método execute() de cada comportamento. Nesse método, os comportamentos manipulam seus sprites associados de alguma forma, dependendo das condições do jogo. Por exemplo, quando você pressiona k para mover a corredora para a direita, o comportamento da corredora de mover lateralmente continua movendo a corredora para a direita em todos os quadros da animação até que você mude a direção. Outro comportamento, correr no lugar, altera periodicamente a imagem da corredora para que ela pareça estar correndo no lugar. Esses dois comportamentos se combinam para dar a impressão de que a corredora está correndo para a esquerda ou para a direita.

A Tabela 1 lista os sprites do jogo e seus respectivos comportamentos:

Tabela 1. Sprites e comportamentos do Snail Bait
SpriteComportamentos
Plataformas
  • Mover horizontalmente (todos os sprites, com exceção da corredora e das bombas de lesma, movem-se em sincronia com as plataformas)
Corredora
  • Correr no lugar
  • Mover lateralmente
  • Pular
  • Cair
  • Chocar-se com os vilões e explodir
  • Chocar-se com as coisas boas e ganhar pontos
Abelhas e morcegos
  • Pairar
  • Bater as asas
Botões
  • Andar
  • Desabar
  • Varia: fazer os vilões explodirem ou terminar o nível
Moedas, rubis e safiras
  • Brilhar
  • Subir e descer
  • Andar
Lesmas
  • Andar
  • Soltar bombas
Bombas de lesma
  • Mover da direita para a esquerda (mais rapidamente que as plataformas)
  • Chocar-se com a corredora e desaparecer

Os artigos seguintes desta série irão abordar os sprites e seus comportamentos de forma mais aprofundada. Por enquanto, para dar a você uma visão geral resumida, a Listagem 1 mostra como o jogo cria o sprite runner :

Listagem 1. Criando sprites
var runInPlace = {  // Just an object with an execute method
   execute: function (sprite, time, fps) {
      // Update the sprite's attributes based on the time and frame rate
   }
};

var runner = new Sprite('runner', // name
                        runnerPainter, // painter
                        [ runInPlace,... ]); // behaviors

Um objeto runInPlace é definido e passado, em um array com outros comportamentos, para o construtor do sprite da corredora. Enquanto está correndo, o jogo chama o método execute() do objeto runInPlace para todos os quadros de animação.


Melhores práticas de desenvolvimento de jogos em HTML5

Ativos gratuitos

A maioria dos desenvolvedores de jogos precisam de ajuda com os gráficos, efeitos sonoros e música. Felizmente, há muitos ativos gratuitos sob vários arranjos de licenciamento.

O Snail Bait usa:

  • Efeitos sonoros de freesound.org
  • Trilha sonora de soundclick.com
  • Sprite da corredora de panelmonkey.org (o site foi hackeado)
  • Todos os outros gráficos são do Replica Island

Eu tratarei das melhores práticas do desenvolvimento de jogos ao longo desta série, começando neste artigo com cinco que são específicas para o HTML5:

Analisarei essas cinco em artigos posteriores desta série; por enquanto, apresentarei uma visão geral de cada uma.

1. Pausar o jogo quando a janela perder o foco

Se um jogo de HTML5 está executando em um navegador e você muda o foco para outra guia ou janela do navegador, a maioria dos navegadores limita severamente a taxa de quadros com a qual a animação do jogo executa, para poupar recursos como CPU e energia da bateria. Essa limitação da taxa de quadros, por sua vez, sempre causa um estrago nos algoritmos de detecção de colisões, que esperam que o jogo execute a uma taxa de quadros mínima. Para evitar as limitações de taxa de quadros e o consequente desastre na detecção de colisões, pause o jogo automaticamente quando a janela perder o foco.

2. Implementar uma contagem regressiva quando a janela recuperar o foco

Quando a janela do jogo recuperar o foco, é recomendável dar ao usuário alguns segundos para se preparar para o reinício do jogo. O Snail Bait usa uma contagem regressiva de três segundos quando a janela recupera o foco, como mostra a Figura 3:

Figura 3. Pausa automática do Snail Bait
Pausa automática do Snail Bait

3. Usar transições de CSS3

A Figura 4 é uma captura de tela obtida após o carregamento do jogo:

Figura 4. Efeitos do CSS3
Efeitos do CSS3

Há dois aspectos a serem ressaltados na Figura 4. Primeiro, uma mensagem — algo que é mostrado brevemente para o cliente — fica visível. A mensagem é Good luck!. Essa frase aparece de forma gradual quando o jogo carrega e, depois de cinco segundos, desaparece da mesma forma. Em segundo lugar, observe as caixas de seleção (referentes ao som e à música) e as instruções (que mostram a função das teclas) abaixo da tela do jogo. Quando o jogo começa, as caixas de seleção e as instruções são totalmente opacas, como mostra a Figura 4; depois do início do jogo, esses elementos desaparecem gradualmente até ficarem quase invisíveis (como mostra a Figura 3), para que não sejam um fator de distração.

O Snail Bait obscurece os elementos e faz as mensagens desaparecerem gradualmente com transições de CSS3.

4. Detectar jogos lentos e reagir a eles

Ao contrário dos jogos de console, que executam em um ambiente rigorosamente controlado, os jogos em HTML5 executam em um ambiente altamente variável, imprevisível e caótico. Não é raro que o seu jogo execute de forma inaceitavelmente lenta quando os jogadores estão reproduzindo vídeos do YouTube em outra guia ou sobrecarregando a CPU ou GPU de outra forma. E sempre existe a possibilidade de que os jogadores usem um navegador que não acompanha a velocidade do jogo.

Como desenvolvedor do jogo, você deve prever essa confluência desfavorável de eventos e reagir adequadamente. O Snail Bait monitora constantemente a taxa de quadros e, quando detecta que ela fica abaixo de um limite específico um certo número e vezes em um determinado período em segundos, ele mostra a mensagem sobre lentidão, mostrada na Figura 5:

Figura 5. Detecção de uma taxa lenta de quadros por segundo
Detecção de uma taxa lenta de quadros por segundo

5. Incorporar recursos sociais

Quase todos os jogos de sucesso incorporam aspectos sociais, como a postagem das pontuações no Twitter ou Facebook. Quando um jogador do Snail Bait clica no link Tweet my score que aparece no final do jogo (veja a Figura 2), o Snail Bait acessa o Twitter em uma guia separada e cria automaticamente um tweet anunciando a pontuação, como a mostrada na Figura 7:

Figura 7. Texto do Tweet
Texto do Tweet

Agora que você tem um entendimento geral em relação ao jogo, é hora de dar uma olhada no código.


HTML e CSS do Snail Bait

Estatísticas do código do Snail Bait

Linhas de código:

  • HTML: 276
  • CSS: 410
  • JavaScript: 3.898

O Snail Bait é implementado com HTML, CSS e JavaScript; no entanto, como é possível ver na barra lateral Estatísticas do código do Snail Bait , a maior parte do código é de JavaScript. Na verdade, o restante desta série trata principalmente do JavaScript, com algumas explicações ocasionais sobre HTML e CSS3.

A Figura 8 mostra os elementos HTML e o CSS correspondente do jogo propriamente dito, omitindo o HTML e o CSS de outros elementos, como mensagens e créditos:

Figura 8. O HTML e CSS do jogo (declarações de sombra da caixa omitidas)
O HTML e CSS do jogo (declarações de sombra da caixa omitidas)

Clique para ver a imagem maior

Figura 8. O HTML e CSS do jogo (declarações de sombra da caixa omitidas)

O HTML e CSS do jogo (declarações de sombra da caixa omitidas)

O CSS não tem praticamente nada diferente, com exceção de alguns atributos de interesse que eu destaquei na Figura 8. Primeiro, configurei o atributo margin do elemento wrapper como 0 auto — ou seja, o wrapper e tudo o que está dentro dele, é centrado horizontalmente na janela. Em segundo lugar, os elementos lives e sound-and-music têm uma posiçãoabsolute . Se você os deixar na posição padrão, que é relative, os DIVs irão se expandir para a largura da tela, e seus vizinhos (pontuação e instruções, respectivamente) irão para baixo deles. Por fim, as classes de CSS keys e explanation CSS têm um atributo display de inline para colocar os elementos associados na mesma linha.

A Listagem 2 mostra o CSS da Figura 8:

Listagem 2. game.css (excerpt)
#arena {
   text-align: center;
   padding: 5px;
   width: 805px;
   height: 445px;
}

#copyright {
   margin-top: -35px;
   float: right;
   margin-right: 12px;
   padding: 2px;
   color: blue;
   text-shadow: 1px 1px 1px rgba(255,255,255,0.7);
   font-size: 0.8em;
}

.explanation {
   color: #ff0;
   text-shadow: 1px 1px 1px rgba(0,0,0,1.0);
   display: inline;
   margin-top: 5px;
   padding-right: 5px;
   padding-left: 5px;
   padding-bottom: 2px;
}
         
#game-canvas {
   border: 2px inset rgba(0,0,80,0.62);
   -webkit-box-shadow: rgba(0,0,0,0.5) 8px 8px 16px;
   -moz-box-shadow: rgba(0,0,0,0.5) 8px 8px 16px;
   -o-box-shadow: rgba(0,0,0,0.5) 8px 8px 16px;
   box-shadow: rgba(0,0,0,0.5) 8px 8px 16px;
}

#instructions {
   height: 30px;
   margin-right: 8px;
   padding-top: 6px;
   padding-left: 25px;

   -webkit-transition: opacity 2s;
   -moz-transition: opacity 2s;
   -o-transition: opacity 2s;
   transition: opacity 2s;

   color: #ff0;
   font-size: 1.05em;
   opacity: 1.0;
}

.keys {
   color: blue;
   text-shadow: 1px 1px 1px rgba(255,255,0,1.0);
   background: rgba(0,0,0,0.1);
   border: thin solid rgba(0,0,0,0.20);
   border-radius: 5px;
   margin-left: 10px;
   padding-right: 10px;
   padding-left: 10px;
   padding-bottom: 5px;
   display: inline;
}

#sound-and-music {
   position: absolute;
   top: 495px;
   margin-left: 10px;
   color: #ff0;
   text-shadow: 1px 1px 1px rgba(0,0,0,0.5);
   background: rgba(0,0,0,0.1);
   border-radius: 5px;
   border: thin solid rgba(0,0,0,0.20);
   padding-top: 2px;
   padding-bottom: 2px;
   z-index: 1;
}

#wrapper {
   margin: 0 auto;
   margin-top: 20px;
   padding: 5px;
   width: 817px;
   height: 520px;
}

Como é possível ver na Listagem 3, que lista o HTML mostrado na Figura 8, o HTML do jogo é formado por um monte de DIVs e uma tela, com algumas imagens e duas caixas de seleção:

Listagem 3. game.html (excerpt)
<!DOCTYPE html>
<html>
   <!-- Head........................................................-->

   <head>
     <title>Snail Bait</title>
   </head>

   <!-- Body........................................................-->

   <body>
      <!-- Wrapper..................................................-->

      <div id='wrapper'>
         <!-- Header.................................................-->

         <div id='header'>
            <div id='lives'>
               <img id='life-icon-left'   src='images/runner-small.png'/>
               <img id='life-icon-middle' src='images/runner-small.png'/>
               <img id='life-icon-right'  src='images/runner-small.png'/>
            </div>

            <div id='score'>0</div>
            <div id='fps'></div>
         </div>

         <!-- Arena..................................................-->

         <div id='arena'>
            <!-- The game canvas.....................................-->

            <canvas id='game-canvas' width='800' height='400'>
               Your browser does not support HTML5 Canvas.
            </canvas>

            <!-- Sound and music.....................................-->

            <div id='sound-and-music'>
               <div class='checkbox-div'>
                  Sound <input id='sound-checkbox'
                                  type='checkbox' checked/>
               </div>
   
               <div class='checkbox-div'>
                  Music <input id='music-checkbox' 
                                  type='checkbox' checked/>
               </div>
            </div>

            <!-- Instructions........................................-->

            <div id='instructions'>
               <div class='keys'>
                  d / k

                  <div class='explanation'>
                     move left/right
                  </div>
               </div>

               <div class='keys'>
                  f / j

                  <div class='explanation'>
                     jump
                  </div>
               </div>

               <div class='keys'>
                  p

                  <div class='explanation'>
                     pause

                  </div>
               </div>
            </div>

            <!-- Copyright...........................................-->

            <div id='copyright'> ©2012 David Geary</div>
         </div>
      </div>

      <!-- JavaScript................................................-->

      <script src='js/stopwatch.js'></script>
      <script src='js/animationTimer.js'></script>
      <script src='js/sprites.js'></script>
      <script src='js/requestNextAnimationFrame.js'></script>
      <script src='js/behaviors/bounce.js'></script>
      <script src='js/behaviors/cycle.js'></script>
      <script src='js/behaviors/pulse.js'></script>
      <script src='game.js'></script>
  </body>
</html>

É no elemento canvas que toda a ação acontece. Essa tela vem com um contexto 2D que tem uma API eficiente para implementar jogos em 2D, entre outras coisas. O texto dentro do elemento canvas é um texto de fallback que o navegador só exibe são não suporta a tela de HTML5.

Uma última observação sobre o HTML e CSS do jogo: observe que a largura e altura da tela são especificadas com os atributos width e height do elemento canvas . Esses atributos se referem ao tamanho do elemento canvase o tamanho da superfície de desenho contida nesse elemento.

Por outro lado, o uso do CSS para configurar a largura e altura do elemento canvas somente define o tamanho do elemento. A superfície de desenho permanece com a largura e altura padrão de 300 e 150 pixels, respectivamente. Isso significa que provavelmente haverá uma incompatibilidade entre o tamanho do elemento canvas e o tamanho da superfície de desenho. Quando isso acontece, o navegador ajusta a escala da superfície de desenho para se ajustar ao elemento. Na maior parte do tempo, esse efeito não é desejado — portanto, é recomendável não configurar o tamanho do elemento canvas com CSS.

Desenhar em uma tela pequena e deixar o CSS ajustar a escala?

Alguns jogos desenham propositalmente em uma tela pequena e usam o CSS para ajustar a sua escala para um tamanho que possibilite o jogo. Dessa forma, você não manipula tantos pixels da tela, aumentando o desempenho. Normalmente, o ajuste de escala da tela com o CSS é acelerado pelo hardware, para que o custo do ajuste de escala seja mínimo. Entretanto, atualmente — já que todas as versões mais recentes dos navegadores modernos estão equipadas com tela acelerada pelo hardware — na maioria dos casos, desenhar em uma tela de tamanho completo é tão rápido quanto desenhar em uma tela pequena.

Como acontece nos bons filmes, como Pulp Fiction, você já viu o fim da história. Eu voltarei para o começo.


O início humilde do Snail Bait

A Figura 9 mostra o ponto de partida do jogo, que simplesmente desenha o plano de fundo, as plataformas e a corredora. Para começar, as plataformas e a corredora não são sprites; em vez disso, o jogo as desenha diretamente. Consulte Download para obter o código que cria o plano de fundo e a corredora.

Figura 9. Desenhando o plano de fundo e a corredora
Desenhando o plano de fundo e a corredora

A Listagem 3 lista o ponto de partida do HTML do jogo, que é apenas uma versão em escala reduzida do HTML na Listagem 2:

Listagem 3. game.html (versão inicial)
<!DOCTYPE html>
<html>
   <!-- Head.........................................................-->

   <head>
      <title>Snail Bait</title>
      <link rel='stylesheet' href='game.css'/>
   </head>

   <!-- Body.........................................................-->

   <body>
      <!-- Wrapper...................................................-->

      <div id='wrapper'>
         <!-- Header.................................................-->

         <div id='header'>
            <div id='score'>0</div>
         </div>

         <!-- Arena..................................................-->

         <div id='arena'>
            <!-- The game canvas.....................................-->

            <canvas id='game-canvas' width='800' height='400'>
               Your browser does not support HTML5 Canvas.
            </canvas>
         </div>
      </div>

      <!-- JavaScript................................................-->

      <script src='game.js'></script>
  </body>
</html>

A Listagem 4 mostra o JavaScript:

Listagem 4. game.js (versão inicial)
// --------------------------- DECLARATIONS ----------------------------

var canvas = document.getElementById('game-canvas'),
    context = canvas.getContext('2d'),

   // Constants............................................................

   PLATFORM_HEIGHT = 8,  
   PLATFORM_STROKE_WIDTH = 2,
   PLATFORM_STROKE_STYLE = 'rgb(0,0,0)',

   STARTING_RUNNER_LEFT = 50,
   STARTING_RUNNER_TRACK = 1,

   // Track baselines
   //
   // Platforms move along tracks. The constants that follow define
   // the Y coordinate (from the top of the canvas) for each track.

   TRACK_1_BASELINE = 323,
   TRACK_2_BASELINE = 223,
   TRACK_3_BASELINE = 123,

   // Images

   background  = new Image(),
   runnerImage = new Image(),

   // Platforms
   //
   // Each platform has its own fill style, but the stroke style is
   // the same for each platform.

   platformData = [  // One screen for now
      // Screen 1.......................................................
      {
         left:      10,
         width:     230,
         height:    PLATFORM_HEIGHT,
         fillStyle: 'rgb(255,255,0)',
         opacity:   0.5,
         track:     1,
         pulsate:   false,
      },

      {  left:      250,
         width:     100,
         height:    PLATFORM_HEIGHT,
         fillStyle: 'rgb(150,190,255)',
         opacity:   1.0,
         track:     2,
         pulsate:   false,
      },

      {  left:      400,
         width:     125,
         height:    PLATFORM_HEIGHT,
         fillStyle: 'rgb(250,0,0)',
         opacity:   1.0,
         track:     3,
         pulsate:   false
      },

      {  left:      633,
         width:     100,
         height:    PLATFORM_HEIGHT,
         fillStyle: 'rgb(255,255,0)',
         opacity:   1.0,
         track:     1,
         pulsate:   false,
      },
   ];

// ------------------------- INITIALIZATION ----------------------------

function initializeImages() {
   background.src = 'images/background_level_one_dark_red.png';
   runnerImage.src = 'images/runner.png';

   background.onload = function (e) {
      startGame();
   };
}

function drawBackground() {
   context.drawImage(background, 0, 0);
}

function calculatePlatformTop(track) {
   var top;

   if      (track === 1) { top = TRACK_1_BASELINE; }
   else if (track === 2) { top = TRACK_2_BASELINE; }
   else if (track === 3) { top = TRACK_3_BASELINE; }

   return top;
}

function drawPlatforms() {
   var pd, top;

   context.save(); // Save context attributes on a stack
   
   for (var i=0; i < platformData.length; ++i) {
      pd = platformData[i];
      top = calculatePlatformTop(pd.track);

      context.lineWidth = PLATFORM_STROKE_WIDTH;
      context.strokeStyle = PLATFORM_STROKE_STYLE;
      context.fillStyle = pd.fillStyle;
      context.globalAlpha = pd.opacity;

      // If you switch the order of the following two
      // calls, the stroke will appear thicker.
      
      context.strokeRect(pd.left, top, pd.width, pd.height);
      context.fillRect  (pd.left, top, pd.width, pd.height);
   }

   context.restore(); // Restore context attributes
}

function drawRunner() {
   context.drawImage(runnerImage,
      STARTING_RUNNER_LEFT,
      calculatePlatformTop(STARTING_RUNNER_TRACK) - runnerImage.height);
}

function draw(now) {
   drawBackground();
   drawPlatforms();
   drawRunner();
}

function startGame() {
   draw();
}

// Launch game

initializeImages();

O JavaScript acessa o elemento canvas e posteriormente obtém uma referência ao contexto 2D da tela. Em seguida, o código usa o método drawImage() do contexto para desenhar o plano de fundo e as imagens da corredora. Nesse caso, estou usando a variante com três argumentos de drawImage() para desenhar imagens em um destino (x,y) específico na tela.

A função drawPlatforms() desenha as plataformas traçando o preenchendo retângulos depois de configurar a largura da linha, estilo do traço, estilo de preenchimento e o atributo global alfabético do contexto. Observe as chamadas a context.save() e context.restore(): as configurações de atributo entre essas chamadas são temporárias. Irei abordar esses métodos no próximo artigo da série.

O jogo inicia quando a imagem de plano de fundo é carregada. Por enquanto, o início envolve simplesmente desenhar o plano de fundo, os sprites e a corredora. O próximo desafio é dar vida a essas imagens estáticas.


Da próxima vez

No próximo artigo desta série, iniciarei uma visão geral da API 2D de contexto da lona e, em seguida, irei tratar da animação e colocar o jogo em movimento fazendo a rolagem do plano de fundo. Você verá como implementar a paralaxe para fazer com que as plataformas pareçam estar mais próximas que o plano de fundo e como garantir que os seus sprites sejam animados a uma taxa constante, independentemente da taxa de quadros da animação. Vejo você na próxima.


Download

DescriçãoNomeTamanho
Code for Snail Bait's background and runnerj-html5-game1.zip718KB

Recursos

Aprender

Obter produtos e tecnologias

  • Replica Island: é possível fazer o download do código-fonte desse videogame de plataforma bastante conhecido de software livre para Android.

Discutir

  • Participe da Comunidade do developerWorks. Entre em contato com outros usuários do developerWorks, enquanto explora os blogs, fóruns, grupos e wikis orientados ao desenvolvedor.

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Tecnologia Java, Software livre
ArticleID=836502
ArticleTitle=Desenvolvimento de Jogos 2D em HTML5: Apresentando o Snail Bait
publish-date=09252012