Desenvolvendo Jogos em HTML5 – Parte 1


Já tem algum tempo que o HTML5 esta ai, nenhum browser ainda suporta todas as suas funcionalidades, mas mesmo assim o desenvolvimento em HTML5 já esta começando a ameaçar o Flash Player.

A Apple decidiu comprar uma briga (na minha opinião não justificada) com a Adobe ao decidir que o IOS não teria suporte ao Flash e deu um empurrãozinho no HTML5, antes disso pouca gente realmente já estava antenado no assunto.

Na minha opinião, o Flash é superior em vários aspectos ao HTML5, começando pela orientação a objetos e a integração do AS3 com diversas outras linguagens e tecnologias, sejam da Adobe ou não. O AS3 vai muito alem de fazer sites e o HTML5 tem seus pontos fortes também, a verdade é que o HTML5 não vai substituir o Flash totalmente como a Apple gostaria e os dois vão continuar existindo por um bom tempo.

Para me manter atualizado decidi dar uma olhada no HTML5 e gostei bastante, sempre gostei de bibliotecas gráficas, e decidi escrever um tutorial misturando um pouco do meu gosto por desenvolvimento de jogos.

Este tutorial será dividido em vários posts curtos, conforme eu for fazendo o jogo vou postando as partes do código, minha intenção é manter os posts rápidos e frequentes, para facilitar a leitura de todos os posts estou criando a categoria Tutoriais / HTML 5.

O jogo criado será relativamente simples, um clone de Paciência Spider, onde tentarei usar o minimo de imagens possíveis e explorar o poder do canvas, novo recurso do HTML 5.
Como eu escreverei o jogo junto com os posts e conforme eu for estudando HTML5 talvez em algum momento eu decida mudar boa parte do que já foi feito.

A principal ferramenta que usaremos será a curva quadrática, para quem nunca ouviu falar, a curva quadrática é uma curva construída com base em 3 pontos: início, fim e um “ponto de fuga”, a curva é construída a partir do binômio de newton e a equação para resolve-la foi criada pelo matemático francês Pierre Bezier, que definiu um método para calculo de uma curva com n pontos, antes disso os algoritmos que calculavam a curva eram ridiculamente ineficientes.

Curva Quadratica de Bezier

O jeito mais fácil de explicar como essa equação se comporta é colar aqui alguns gifs da wikipedia 😉

Curva linear
Curva linear
Curva quadrática
Curva quadrática
Curva Cúbica
Curva Cúbica
Curva de ordem superior
Curva de ordem superior

Com isso claro podemos passar para HTML5, que nos fornece a ferramenta canvas, similar a varias linguagens, que é uma “área de desenho” e possui algumas funções prontas, como moveTo(x,y), lineTo(x, y), quadraticCurveTo(x1,y1,x2,y2) e outras que nos serão muito úteis.
Começamos com a criação do canvas:

<canvas id="myGame" width="200" height="350">
<p>Seu navegador não suporta HTML5!</p>
</canvas>

Depois criamos a função que desenhará a borda da carta:

function cardBorderDraw(canvasName, x1,y1,x2,y2, r) { }

Essa função recebe o nome do canvas em que deve desenhar a carta, x e y do ponto superior esquerdo da carta, x e y do ponto inferior direito e r que é o raio da curva nas bordas.

Começamos a função com a atribuição do contexto do canvas à uma variável:

var drawingCanvas = document.getElementById(canvasName);
if(drawingCanvas && drawingCanvas.getContext) {
var context = drawingCanvas.getContext('2d');
}

Assim podemos usar a variável context para desenhar, usaremos as funções citadas acima com um pouco de matemática simples para calcular o formato da carta. Vale lembrar que em computação não usamos o plano cartesiano convencional, onde a origem fica no centro com y crescendo verticalmente, usamos a contagem de pixel do monitor que começa no canto superior esquerdo com y crescendo para baixo.

Plano cartesiano convencional
Plano cartesiano convencional
Plano cartesiano do computador
Plano cartesiano do computador

Dito isso vamos ao desenho da borda, começaremos pelo ponto (x1,y1) no canto superior esquerdo e deslocamos r em x pois a borda será desenhada posteriormente a partir do ponto final do contorno, traçamos uma linha até (x2,y1) descontando a borda r, que fica (x2-r, y1), então usamos a nossa querida curva quadrática para desenhar a curva entre o ponto de origem (x2-r, y1) com desvio para (x2,y1) e com termino em (x2,y1+r), preste atenção que pela natureza das coordenadas eu somei r em y1 e não subtrai como seria o normal. Com isso desenhamos a linha superior e a borda superior direita, para concluir a carta basta seguir o mesmo processo, e depois preencher, o código JS para isso é o seguinte:

context.beginPath(); // inicia o desenho da carta
context.moveTo(x1+r, y1);
context.lineTo(x2-r, y1);
context.quadraticCurveTo(x2, y1, x2, y1+r);
context.lineTo(x2, y2-r);
context.quadraticCurveTo(x2, y2, x2-r, y2);
context.lineTo(x1+r, y2);
context.quadraticCurveTo(x1, y2, x1, y2-r);
context.lineTo(x1, y1+r);
context.quadraticCurveTo(x1, y1, x1+r, y1);
context.closePath();
context.stroke(); // executa o desenho linhas
context.fillStyle = "#FFFFFF"; //preenche para o drop shadow
context.fill()

Como indicado pelo comentário, é preciso preencher a carta para o Drop Shadow funcionar, que pra quem não sabe é o efeito de sombra feito automaticamente por quase todo software e apid que manipula imagens. Para criar um efeito de Drop Shadow insira essas linhas antes do desenho da carta:

//Liga o Drop Shadow
context.shadowOffsetX = 10;
context.shadowOffsetY = 10;
context.shadowBlur = 10;
context.shadowColor = "gray";

Isso vai ativar o Drop Shadow e tudo que for desenhado após isso terá uma sombra, criado o nosso contorno em volta da carta desabilitamos a sombra com essas linhas depois do desenho da carta:

//Desliga o drop shadow
context.shadowOffsetX = 0;
context.shadowOffsetY = 0;
context.shadowBlur = 0;
context.shadowColor = "transparent";

Vamos agora criar uma função que desenha a carta completa, essa função será chamada ao abrir o arquivo para podermos ver o que está acontecendo:

window.onload = function() {
DrawCardBack('myGame',10,10,160,210)
};
function DrawCardBack(canvasName, x1,y1,x2,y2)
{
r = 10;
cardBorderDraw(canvasName,x1,y1,x2,y2,r);
}

Ao acessar o arquivo o resultado que você deve ver é esse:

Vamos ao centro do desenho, agora desenharemos aparte de trás da carta com a função:

function cardBackDraw(canvasName, x1,y1,x2,y2, r, nLinhasTextura) {
var drawingCanvas = document.getElementById(canvasName);
if(drawingCanvas &amp;&amp; drawingCanvas.getContext) {
var context = drawingCanvas.getContext('2d');

Primero definimos um gradiente radial para o preenchimento, ou seja um degrade circular centrado no ponto médio da carta:

//gradiente do preenchimento
cx = x1 + (x2 - x1) / 2;
cy = y1 + (y2 - y1) / 2;
var gradient = context.createRadialGradient(cx,cy,0,cx,cy,(y2 - y1));
gradient.addColorStop(0, '#FF0000');
gradient.addColorStop(1, '#660000');

Repare que em createRadialGradient eu usei o mesmo centro, as outras variáveis são os raios das cores. Em seguida desenhamos a borda como feito ateriormente, mas dessa vez utilizamos o gradiente como preenchimento:

// desenho da carta
context.beginPath();
context.moveTo(x1+r, y1);
context.lineTo(x2-r, y1);
context.quadraticCurveTo(x2, y1, x2, y1+r);
context.lineTo(x2, y2-r);
context.quadraticCurveTo(x2, y2, x2-r, y2);
context.lineTo(x1+r, y2);
context.quadraticCurveTo(x1, y2, x1, y2-r);
context.lineTo(x1, y1+r);
context.quadraticCurveTo(x1, y1, x1+r, y1);
//executa prenchimento
context.fillStyle = gradient;
context.fill();

E agora o que talvez seja a parte mais complicada da carta, vamos criar um desenho simples na carta usando a mesma ideia da curva quadrática, usando como referencia 3 dos quato cantos da carta e um espaçamento padrão, desenhamos varias linhas, que seriam as linhas de construção da curva:

//linhas textura
distLinhasx = ((x2 - x1) - r -r)/nLinhasTextura;
distLinhasy = ((y2 - y1) - r -r)/nLinhasTextura;
for(var i = 0; i
{
context.moveTo((x1+r+(distLinhasx*i)),y1);
context.lineTo(x2, y1+r+(distLinhasy*i));
}
for(var i = 0; i
{
context.moveTo((x1+r+(distLinhasx*i)),y2);
context.lineTo(x1, y1+r+(distLinhasy*i));
}
context.closePath();
context.stroke(); // executa linhas
}

Observe que eu fiz isso duas vezes e considerei a distancia r da borda para não desenhar fora da curva, divirta-se brincando com essa função para criar outros baralhos, agora altere a função DrawCardBack para ficar assim:

function DrawCardBack(canvasName, x1,y1,x2,y2)
{
r = 10;
linhas = 20
cardBorderDraw(canvasName,x1,y1,x2,y2,r);
cardBackDraw(canvasName,x1+r,y1+r,x2-r,y2-r,r,linhas);
}

E veja o resultado:

Por ultimo vamos mudar o fundo para verde, para ficar mais caracteristico de um jogo de cartas, e mudar a sombra para preto para combinar com o fundo, altere as seguintes linhas no seu arquivo:

<canvas id="myGame" width="800" height="600" style="background:green;">

e

context.shadowColor = "black";

O resultado final é esse:

cardfinal
Resultado final

O arquivo pode ser baixado aqui, e pode ser visualizado aqui.
Acredito que já é muito coisa para um post só, espero que tenham gostado e tentarei ser breve em escrever o proximo.


6 respostas para “Desenvolvendo Jogos em HTML5 – Parte 1”

  1. Ameii o post… espero que tu continues a postar sobre o desenvolvimento do jogo de cartas. Estou tentando aprender um pouco de canvas, e teu tutorial foi de muita ajuda. Aguardando a parte 2 (:
    Abraço

  2. Cara legal teu tutorial, podemos ver que o canvas é incrivel, qual teu email, toh começando a utilizar o html5 e preciso de umas dicas!!!!se puder me ajudar fico grato!!!!VLW

  3. o html é uma linguagem bem modelada se encaixa em muitas outras linguagens, será possivel no futuro a integração do flash com o html?