Desenvolvimento - HTML

HTML5 Canvas: Movendo um personagem com Sprites

Veja neste artigo como trabalhar com o HTML5 Canvas e veja como movimentar um personagem usando Sprites.

por Joel Rodrigues



Introdução ao HTML5 Canvas

Já sabemos que com a ascensão da HTML5 e do avanço da Javascript e CSS se tornou possível desenvolver jogos completos utilizando basicamente as web standards. Isso não indica que plataformas já consolidadas como o Flash e XNA vão cair em desuso, pelo menos não agora, mas significou um grande avanço para os entusiastas do desenvolvimento de games para web que passaram a ficar menos dependentes de outras tecnologias.

Como em qualquer jogo que utilize “chars” (personagens), um dos primeiros passos é desenhar e mover um “boneco”. Inicialmente costuma-se praticar com objetos de forma fixa (um círculo, um retângulo, etc.) e em seguida se passa a usar objetos de forma variável. Nessa categoria entram os diversos personagens do jogo, que tem sua forma alterada durante o deslocamento (para dar ideia de movimento de pernas, braços, etc.).

Algumas engines mais poderosas possuem funcionalidades para fazer essa movimentação de forma prática, fornecendo e utilizando modelos (principalmente 3D), cujos movimentos são definidos em um trabalho de modelagem do personagem. Porém, em engines mais simples (principalmente as 2D), a forma mais utilizada para se desenhar e movimentar esses personagens é utilizando SPRITES, técnica que será explicada mais adiante.

Nesse artigo veremos como utilizar essa técnica com a tag CANVAS da HTML5 e auxílio da linguagem Javascript para movimentar um personagem em uma página html.

Observação: aqui implementaremos o movimento em apenas uma direção (para a direita), que será controlado pela seta do teclado. O leitor que se interessar pode utilizar a mesma técnica para desenvolver os demais movimentos e incrementar o exemplo conforme sua necessidade.

Sprites

Sprites, como são chamados, são imagens contendo várias formas/posições de um ou vários objetos. Por exemplo, um sprite para um determinado personagem deve possuir “cenas”, posições suas se movimentando. Por exemplo, ele parado, dando um passo com a perna direita, dando um passo com a perna esquerda, etc.

A figura a seguir mostra o sprite que foi utilizado neste artigo, imagem obtida na internet.

Sprite utilizado

Figura 1: Sprite utilizado

Como vemos, a imagem armazena vários momentos do deslocamento de um rapaz indo para a direita.

A técnica de utilizar sprites para dar a ideia de movimento consiste em recortar partes da imagem e desenhá-las, na área reservada para esse fim, em sequência. Para isso, as dimensões de cada parte devem ser bem definidas e conhecidas pelo programador que poderá dividir a imagem original em várias partes e usar somente aquela referente a posição atual.

Como o objetivo desse artigo não é explicar como recortar imagens usando Javascript, utilizaremos outra forma um pouco menos prática, mas que também funciona e resulta no mesmo efeito.

O que faremos é recortar as imagens previamente utilizando um editor de imagens qualquer, salvando cada posição em um arquivo separado. É importante que todas as partes tenham a mesma dimensão e que o personagem seja posicionado da mesma forma em todas elas. No caso, utilizaremos imagens de dimensões 200x340px e o posicionaremos no canto inferior esquerdo do quadro. Salvaremos então cada imagem com um número que indica a posição no deslocamento, sendo 0 (zero) a primeira onde o personagem está parado. Teremos então as imagens 0.png, 1.png, até 6.png.

O código HTML

O código HTML utilizado é bastante simples e consiste basicamente de uma tag CANVAS (além da estrutura básica da página) e referência a um arquivo Javascript que desenvolveremos posteriormente.

Listagem 1: Código HTML da página

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>Canvas</title>
</head>
<body>
    <div>
        <canvas id="canvas" width="1000" height="340" style="background:rgb(233,233,233)">
        Se você visualizar esse texto, seu browser não suporta a tag canvas.
        </canvas>
    </div>
    <script type="text/javascript" src="desenhar_personagem.js"></script>
</body>
</html>

A referência ao script foi feita após a tag canvas para garantir que a canvas já estará carregada (ou não) quando o script for interpretado.

Usamos a cor RGB(233, 233, 233) por ser a mesma do plano de fundo da imagem que tomamos como exemplo.

Passamos então para a parte principal do código, o script Javascript que “dá vida” ao personagem.

O código Javascript

A seguir serão apresentados os vários trechos de código do arquivo desenhar_personagem.js, que deve ser salvo no mesmo diretório do html e das imagens, para facilitar a compreensão e utilização. Os códigos é apresentado em uma ordem lógica, então fica como sugestão inseri-los no arquivo na sequência em que aparecem aqui.

Listagem 2: Declaração de variáveis

var canvas;//o elemento canvas sobre o qual desenharemos
var ctx;//o "contexto" da canvas que será utilizado (2D ou 3D)
var dx = 50;//a taxa de variação (velocidade) horizontal do objeto
var x = 30;//posição horizontal do objeto (com valor inicial)
var y = 0;//posição vertical do objeto (com valor inicial)
var WIDTH = 1000;//largura da área retangular
var HEIGHT = 340;//altura da área retangular
var tile1 = new Image();//Imagem que será carregada e desenhada na canvas
var posicao = 0;//Indicador da posição atual do personagem
var NUM_POSICOES = 6;//Quantidade de imagens que compõem o movimento

Todas as linhas da listagem acima estão comentadas, explicando cada variável declarada, então dispensa maiores detalhes.

Listagem 3: Função KeyDown

function KeyDown(evt){
    switch (evt.keyCode) {
        case 39:  /*seta para direita*/
            if (x + dx < WIDTH){
                x += dx;
                posicao++;
                if(posicao == NUM_POSICOES)
                    posicao = 1;
            }
            break;            
    }
}

Essa função será utilizada para tratar o evento Key Down da página. Como foi dito anteriormente, apenas a seta para a direita foi utilizada para movimentar a o personagem na tela.

Primeiramente verificamos se o movimento está dentro da área reservada, caso esteja, aumentamos as variáveis que indicam a posição horizontal e o estado do “boneco”. Caso o estado do personagem seja o último da sequência de imagens, voltamos para o estado inicial, mantendo assim um movimento cíclico.

Listagem 4: Função Desenhar

function Desenhar() {    
    tile1.src = posicao+".png";
    ctx.drawImage(tile1, x, y);
}

Nessa função utilizamos a variável que indica a posição/estado do personagem e a utilizamos para carregar a respectiva imagem (0, 1, 2...). Em seguida, com a função drawImage do objeto ctx, desenhamos a imagem na área reservada nas coordenas x e y.

Listagem 5: Função LimparTela

function LimparTela() {
    ctx.fillStyle = "rgb(233,233,233)";    
    ctx.beginPath();
    ctx.rect(0, 0, WIDTH, HEIGHT);
    ctx.closePath();
    ctx.fill();    
}

A função LimparTela, como o nome sugere, é usada para limpar o “buffer”, ou seja, redesenhar o plano de fundo da área retangular para que se possa desenhar novamente o personagem sobre ela. Essa função será usada continuamente para que a tela seja limpa e redesenhada, dando a ideia de movimento.

Listagem 6: Função Atualizar

function Atualizar() {
    LimparTela();    
    Desenhar();
}

Essa função é responsável por executar o processo de desenho, chamando as funções LimparTela e Desenhar, nessa ordem. A função atualizar será invocada repetidas vezes, em intervalos de tempo definidos a seguir.

Listagem 7: Função Iniciar

function Iniciar() {
    canvas = document.getElementById("canvas");
    ctx = canvas.getContext("2d");
    return setInterval(Atualizar, 100);
}

Na Listagem 7 temos a função Iniciar, responsável por instanciar os objetos utilizados em todo o código e definir a chamada contínua à função Atualizar. Usando a função setInterval, fazemos com que a Atualizar seja invocada a cada 100 milissegundos, fazendo com que a tela se mantenha atualizada.

Em situações reais, esse intervalo é bem menor, na faixa de 10 ou até 1 milissegundo.

Listagem 8: Iniciando a execução do código

window.addEventListener('keydown', KeyDown);
Iniciar();

A primeira linha de código da listagem acima faz com que a função KeyDown previamente definida seja adicionada como “event handler” do evento keydown da janela.

Em seguida chamamos a função Iniciar que, como visto anteriormente, dá início a todo o processo.

Tendo salvo os arquivos html e js juntamente com as imagens, e abrindo o documento no browser, teremos o seguinte resultado.

Personagem desenhado em movimento

Figura 2: Personagem desenhado em movimento

É possível que ocorram pequenos “atrasos” no desenho e algumas atualizações visíveis da imagem, isso é corrigido com técnicas de buffer muito aplicadas no desenvolvimento de jogos, mas que não serão apresentadas aqui.

Conclusão

O objetivo desse artigo foi de apresentar uma forma de desenhar e movimentar um personagem na tela, usando a tag CANVAS da HTML5 com o auxílio de Javascript.

Como sugestão de leitura complementar ficam alguns links de outros artigos que também utilizam esses recursos para fins semelhantes:

Para fazer o download do código-fonte utilizado nesse exemplo, basta clicar aqui

Agradeço a atenção do leitor e até a próxima.

Joel Rodrigues

Joel Rodrigues - Técnico em Informática - IFRN Cursando Bacharelado em Ciências e Tecnologia - UFRN Programador .NET/C# e Delphi há quase 3 anos, já tendo trabalhado com Webservices, WPF, Windows Phone 7 e ASP.NET, possui ainda conhecimentos em HTML, CSS e Javascript (JQuery).