Tutorial: Como programar um joguinho simples

Desenvolvimento do jogo Breakout

Esse artigo apresenta o desenvolvimento do jogo Breakout para browsers.

screenshot.png

Programando com a linguagem javascript

Vamos começar criando um arquivo em branco chamado jogo.htm Nesse arquivo vamos digitar o código:

<html>
<body>
Daqui vai surgir o jogo
</body>
</html>

Criando o elemento canvas

Vamos apagar a frase e colocar o elemento canvas

<canvas></canvas>

Testando no navegador

Se voce salvar o arquivo e clicar duas vezes sobre ele, o navegador irá exibir uma página em branco. Mas o canvas está lá... Para deixar ele visível vamos colocar uma borda:

<canvas style='border:1px solid #4a4a4a;'></canvas>

Tamanho do canvas

Para setar o tamanho do canvas não se deve usar atributos css. Deve-se usar atributos da tag. Atributos html.

Por uma razão peculiar.

<center><canvas id=canvas width=400 height=450 style='border:1px solid #4a4a4a;'></canvas></center>

Começando a desenhar

O motivo que nos leva a usar o elemento canvas é que ele possibilita desenhar na tela codificando. Os primeiros jogos eletronicos eram em modo texto. Em seguida eram em blocos quadrados. Depois eram desenhados atraves de codificação. Depois vieram os bmp os gif os jpg. os 3d.

Mas esse jogo é da época do quadrado

E usa o canvas que é um elemento que emula um recurso inventado na época do 'desenhar com código'.

Desenhar no canvas

Para desenhar no canvas é preciso de um 'context' E um id pro canvas

e javascript

<html>
<body>
<center><canvas id=canvas width=400 height=450 style='border:1px solid #4a4a4a;'></canvas></center>
<script>
canvas=document.getElementById('canvas').getContext('2d');
</script>
</body>
</html>

Um círculo

Pra desenhar o círculo em vermelho dentro do canvas em preciso de algumas propriedades do 'context'. Alguns métodos e atributos: fillStyle beginPath(); arc(); fill();

canvas.fillStyle='#ff0000';
canvas.beginPath();
canvas.arc(50,125,16,0,Math.PI*2,false);
canvas.fill();

Fazendo a bolinha se mover

Vamos usar a função setTimeout

Pegar esse código que desenha a bolinha e fazer ele ser executado a cada 10 milissegundos. E mudar os dois primeiros parametros da função arc para variáveis x e y, e incrementar essas variáveis cada vez para a bolinha se mover

x=30;
y=15;
function anda()
{	x+=2;
	y+=2;
	canvas.fillStyle='#ff0000';
	canvas.beginPath();
	canvas.arc(x,y,16,0,Math.PI*2,false);
	canvas.fill();
	setTimeout('anda();',10);
}
anda();

Apagando o rastro da bolinha

function anda()
{	x+=2;
	y+=2;
	canvas.fillStyle='#ffffff';
	canvas.fillRect(0,0,400,450);
	canvas.fillStyle='#ff0000';
	canvas.beginPath();
	canvas.arc(x,y,16,0,Math.PI*2,false);
	canvas.fill();
	setTimeout('anda();',10);
}

Fazendo a bolinha pingar nas paredes

Pra isso vamos precisar de novas variáveis dx e dy que vão armazenar quanto a bolinha avança (ou retrocede) no eixos x e y

Vamos mudar o valor de dx e de dy quando a bolinha pingar na parede. (quando ela chegar no chão o dx vai mudar de +2 para -2)

<script>
canvas=document.getElementById('canvas').getContext('2d');
x=20;
y=200;
tamanho=10;
dx=2;
dy=2;
function anda()
{	x+=dx;
	y+=dy;
	if(x<tamanho)dx*=-1;
	if(y<tamanho)dy*=-1;
	if(x>400-tamanho)dx*=-1;
	if(y>450-tamanho)dy*=-1;
	canvas.fillStyle='#ffffff';
	canvas.fillRect(0,0,400,450);
	canvas.fillStyle='#ff0000';
	canvas.beginPath();
	canvas.arc(x,y,tamanho,0,Math.PI*2,false);
	canvas.fill();
	setTimeout('anda();',10);
}
anda();
</script>
</tamanho)dx*=-1;>

Desenhando a barra

Iniciando a posição da barra (fora da função anda)

posicaobarra=150;

Dentro da função anda (após o código que apaga o rastro)

	canvas.fillStyle='#000000';
	canvas.fillRect(posicaobarra,430,100,20);

Fazendo a barra se mover

Pra fazer a barra se mover vamos usar o atributo onKeyDown da tag body

<body onkeyDown='movebarra(event.keyCode);'>

E vamos escrever a função movebarra Inicialmente vamos por um alert pra identificar o código de cada tecla

function movebarra(tecla)
{	alert(tecla);
}

E agora vamos fazer a barra se mover

function movebarra(tecla)
{	//alert(tecla);
	if(tecla==37)posicaobarra-=40;
	if(tecla==39)posicaobarra+=40;
}

Fazendo a bola pingar na barra

Quando a bola acertar a barra a bola deve voltar a subir.

E dependendo de que parte da barra a bola acertar a bola deve voltar em um certo ângulo Vamos modificar a função anda

	if(y>430-tamanho)
	{	dif=x-posicaobarra;
		if(dif>-10&amp;&amp;dif<110)
		{	dy*=-1;
			if(dif>-10&amp;&amp;dif<15)dx=-3;
			if(dif>=15&amp;&amp;dif<50)dx=-2;
			if(dif>=50&amp;&amp;dif<85)dx=2;
			if(dif>=85&amp;&amp;dif<110)dx=3;
			y=430-tamanho;
		}
	}
	if(y>450-tamanho)
		alert('Fim de jogo');
	else
		setTimeout('anda();',10);

Desenhando um bloquinho

Pra começar vamos apenas desenhar um bloquinho. Vamos criar uma variável bloco que será um array com três índices:

bloco=[10,20,true];
	if(bloco[2])
	{	canvas.fillStyle='#0000ff';
		canvas.fillRect(bloco[0],bloco[1],50,20);
	}

Fazendo a bolinha pingar e o bloco desaparecer

	if(bloco[2])
	{	dif=y-bloco[1]-tamanho;
		if((dy<0&amp;&amp;(dif>0&amp;&amp;dif<20))||(dy>0&amp;&amp;(dif<0&amp;&amp;dif>-20)))
		{	if(x>bloco[0]&amp;&amp;x<bloco[0]+50)
			{	dy*=-1;
				bloco[2]=false;
			}
		}
	}

Fazer funcionar com vários blocos

Por enquanto fizemos o jogo funcionar com um bloco Mas vamos precisar de um array de blocos

Vários blocos Vamos colocar antes da declaração do x=20 e y=200 esse trecho de código que inicializa o array de blocos:

blocos=[];
for(x=0;x<8;x++)for(y=0;y<5;y++)blocos.push([x*50,y*20,true]);

E vamos 'refatorar' o código... transformar todas a ocorrencias de bloco em blocos[indice]:

	for(c=0;c<blocos.length;c++)if(blocos[c][2])
	{	dif=y-blocos[c][1]-tamanho;
		if((dy<0&amp;&amp;(dif>0&amp;&amp;dif<20))||(dy>0&amp;&amp;(dif<0&amp;&amp;dif>-20)))
		{	if(x>blocos[c][0]&amp;&amp;x<blocos[c][0]+50)
			{	blocos[c][2]=false;
				dy*=-1;
			}
		}
	}
	for(c=0;c<blocos.length;c++)if(blocos[c][2])
	{	canvas.fillStyle='#0000ff';
		canvas.fillRect(blocos[c][0],blocos[c][1],50,20);
	}

Jogo Finalizado

https://drive.google.com/file/d/1qkPvvymXNm6UX8MpAiIF2YiONFvFFv1Y/view?usp=sharing

Muito bacana teu post Rodrigo, é muito massa criar joguinhos com JavaScript!

Umas dicas:

Usar reset ao invés de fillRect para limpar o canvas.

canvas.reset()

Isso é opcional, mas ao invés de definir uma variável com nome "canvas" defina com "context", geralmente se define com esse nome.

Eu escrevi esse codigo/tutorial antes de 2010. Não existia o chrome. Eu usava o internet explorer e a galera da faculdade falava pra eu mudar pro firefox que tinha abas.