Tutoriais

Rocket Attack

Esse tutorial apresenta o desenvolvimento de um jogo de corrida de navinhas

Arquivo hta

O windows reconhece arquivos com a extensão .hta
Esse tipo de arquivo é executável com um duplo-clique sobre o ícone.
Mas essa extensão de arquivo é particularmente interessante porque o arquivo contém código-fonte html

Criando o arquivo principal

Use um editor de código para criar um arquivo chamado Rocket Attack.hta

Código base

<hta:application border="thin" maximizebutton="no" minimizebutton="no" scroll="no">
<html>
<meta charset=utf-8>
<title>Rocket Attack</title>
<bgsound src="assets/Ankh Wave - Rocket Attack Theme.mp3" loop="infinite">
<link rel="stylesheet" href="style.css"/>
<script src="script.js"></script>
<body onKeyDown="vira(event.keyCode);" onKeyUp="para();">
<center>
	<img id="logotipo" src="assets/logo.png"><br><br>
	<div id="menuPrincipal">
		<input class="itemMenu" onclick="desenhaPista(0); gameLoop();" type=radio> &nbsp;
		<input class="itemMenu" onclick="desenhaPista(1); gameLoop();" type=radio> &nbsp;
		<input class="itemMenu" onclick="desenhaPista(2); gameLoop();" type=radio>
	</div>
</center>
</body>
</html>
Essa é a splashcreen que exibe o logotipo do jogo.
Ela dá a opção para o user selecionar uma das três fases.

Ela starta a musica que foi criada por um músico que colaborou com esse game.

Esse arquivo vincula o arquivo css e o arquivo script.js
No código desse arquivo hta a tag body vincula o pressionamento de tecla com funções javascript que serão apresentadas.

Arquivo css

body{
	background-image:url("assets/fundo.jpg");
}
#btnMiniMapa{
	width:20px;
	position:absolute;
	bottom:6px;
	right:6px;
	cursor:pointer;
}
#ladrilho{
	width:200px;
}
#logotipo{
	width:360px;
	margin-top:136px;
}
#menuPrincipal{
	display:inline;
	padding:4px 10px;
	background-color:#ffffff;
}
#menuLateral{
	position:absolute;
	right:6px;
	top:5px;
	background-color:#ffffff;
	padding:3px 1px 3px 0px;
	z-index:2;
}
#miniMapa{
	position:absolute;
	bottom:4px;
	right:4px;
	background-color:#000000;
	border:1px solid #bbbbbb;
	z-index:2;
	padding:18px 10px 10px 14px;
	cursor:pointer;
}
#nave{
	width:64px;
	position:absolute;
	top:234px;
	left:260px;
	z-index:1;
}
#oponente{
	width:64px;
	position:absolute;
	z-index:1;
}
#tracado{
	position:absolute;
}
.itemMenu{
	cursor:pointer;
}
.ladrilhoMiniMapa{
	width:4px;
	height:4px;
}

O arquivo js

O interessante desse jogo acontece no arquivo javascript.
//colocando a janelinha do jogo no centro da tela com o tamanho correto
window.resizeTo(600,600);
window.moveTo((screen.width-600)/2,(screen.height-600)/2);

//inicializando variaveis que tratam o evento que é disparado quando o user usa o teclado
btnEsqPressionado=false;
btnDirPressionado=false;

//variáveis que indicam quantos pixels a navinha se move no eixo x e no eixo y
fatorDeslocamentoX=[9,8,7,6,5,4,3,2,1,0,-1,-2,-3,-4,-5,-6,-7,-8,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8];
fatorDeslocamentoY=[0,-1,-2,-3,-4,-5,-6,-7,-8,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,8,7,6,5,4,3,2,1];
//quando a nave está inclinada 20 graus (fatorDeslocamentoY[2]) ela desloca -2
//quando a nave está inclinada 40 graus (fatorDeslocamentoX[4]) ela desloca 5

//3 fases
//cada fase um array de array de int
//0 é grama
//1 é seta pra cima
//2 é seta pra baixo
//3 é seta para esquerda
//4 é seta para direita
traçadoPista=[
[[0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0],[0,0,4,4,2,0,4,4,2,0,4,4,2,0,1,3,3,3,3,3,0,0,0],[0,0,1,0,2,0,1,0,2,0,1,0,2,0,0,0,0,0,0,1,0,0,0],[0,0,1,0,4,4,1,0,4,4,1,0,4,4,4,4,4,2,0,1,0,0,0],[0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1,0,0,0],[0,0,1,3,3,3,3,3,3,3,3,3,3,3,3,3,0,2,0,1,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,0,1,0,0,0],[4,4,4,4,4,4,4,4,4,4,4,4,4,2,0,1,0,2,0,1,0,0,0],[1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1,0,2,0,1,0,0,0],[1,3,3,3,3,3,3,3,0,0,0,0,0,2,0,1,0,2,0,1,3,3,3],[0,0,0,0,0,0,0,1,0,0,0,0,0,2,0,1,0,2,0,0,0,0,1],[0,0,0,0,0,0,0,1,0,0,0,0,0,4,4,1,0,4,4,4,4,4,1]],
[[0,0,0,0,0,0,0,0,0,0,0,2,3,3,3,3,3,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,1,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,1,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,1,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,1,3,3,3,3,3,3],[0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,1],[0,0,0,2,3,3,0,2,3,3,0,2,0,0,0,0,0,0,0,0,0,0,1],[0,0,0,2,0,1,0,2,0,1,0,2,0,0,0,0,0,0,0,0,0,0,1],[0,0,0,2,0,1,3,3,0,1,0,2,0,0,0,0,0,0,0,0,4,4,1],[0,0,0,2,0,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,2,0,0,0,0,0,1,0,2,0,0,0,0,4,4,2,0,1,3,3],[3,3,3,3,0,0,0,0,0,1,0,2,0,0,0,0,1,0,2,0,0,0,1],[0,0,0,0,0,0,0,0,0,1,3,3,0,0,0,0,1,0,2,0,0,0,1],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,0,0,0,1],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,4,4,4,4,1]],
[[2,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,2,3,3,3,3,3,0],[2,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,2,0,0,0,0,1,0],[2,0,4,4,4,4,4,4,4,4,2,0,1,0,0,0,2,0,4,4,4,1,0],[2,0,1,0,0,0,0,0,0,0,2,0,1,0,0,0,2,0,1,0,0,0,0],[2,0,1,0,2,3,3,0,0,0,2,0,1,0,0,0,2,0,1,3,3,3,3],[2,0,1,0,2,0,1,0,0,0,2,0,1,0,0,0,2,0,0,0,0,0,1],[2,0,1,0,2,0,1,0,0,0,4,4,1,0,0,0,4,4,4,4,2,0,1],[2,0,1,0,2,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1],[2,0,1,0,2,0,1,0,3,3,3,3,3,3,3,3,3,3,3,3,3,0,1],[2,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],[2,0,1,0,4,4,4,4,2,0,4,4,2,0,4,4,4,4,4,4,4,4,1],[2,0,1,0,0,0,0,0,2,0,1,0,2,0,1,0,0,0,0,0,0,0,0],[2,0,1,3,3,3,3,3,3,0,1,0,2,0,1,0,0,0,0,0,0,0,0],[2,0,0,0,0,0,0,0,0,0,1,0,2,0,1,0,0,0,0,0,0,0,0],[4,4,4,4,4,4,4,4,4,4,1,0,4,4,1,0,0,0,0,0,0,0,0]]
];

//em qual casinha/quadrado/ladrilho as naves iniciam (x,y em cada uma das três fases)
posiçãoInicialLadrilhoX=[13,13,7];
posiçãoInicialLadrilhoY=[6,15,5];
posiçãoFinalLadrilhoX=[0,11,8];
posiçãoFinalLadrilhoY=[2,0,8];

//quando o user pressona uma tecla
function vira(k){
	if(k==37||k==65)btnEsqPressionado=true;
	if(k==39||k==68)btnDirPressionado=true;
}
function para(){
	btnEsqPressionado=false;
	btnDirPressionado=false;
}

//essa função é executada cada vez que a fase é iniciada
function init(){
	btnEsqPressionado=false;
	btnDirPressionado=false;

	//naves apontadas para cima
	angulo=0;
	anguloOponente=0;

	//posição inicial das naves
	posiçãoNaveX=-(posiçãoInicialLadrilhoX[fase]*200)-64;
	posiçãoNaveY=-(posiçãoInicialLadrilhoY[fase]*200)-50;
	posiçãoOponenteX=-(posiçãoInicialLadrilhoX[fase]*200)-64;
	posiçãoOponenteY=-(posiçãoInicialLadrilhoY[fase]*200)+40;

	tempo=0;

	//5 milissegundos de vantagem para a nave oponente
	parado=5;

	//imgs aleatórias para a nave oponente
	oponenteAleatorio=parseInt(Math.random()*4);

	//código que coloca as varias partes da pista em uma table gigante
	htm="<table cellpadding='0' cellspacing='1' onclick='ocultaMiniMapa();'><tr>";
	for(x=0;x<traçadoPista[fase].length;x++){
		for(y=0;y<traçadoPista[fase][x].length;y++)
			htm+="<td class='ladrilhoMiniMapa'"+(traçadoPista[fase][x][y]!=0?" style='background-color:#ffffff;'":"")+" id='ladrilhoMiniMapa"+x+"_"+y+"'> </td>";
		htm+="</tr><tr>";
	}
	document.getElementById('miniMapa').innerHTML=htm+"</tr></table>";
}

//função que é executada várias vezes por segundo durante a gameplay
function gameLoop(){

	//calcula para descobrir em qual casinha/quadrado/ladrilho a nave oponente está
	oponenteLadrilhoX=Math.ceil((-posiçãoOponenteX+64)/200);
	oponenteLadrilhoY=Math.ceil((-posiçãoOponenteY+100)/200);

	//calcula o deslocamento para atualizar a posição da nave oponente
	posiçãoOponenteX+=fatorDeslocamentoX[anguloOponente]*3.14;
	posiçãoOponenteY+=fatorDeslocamentoY[anguloOponente]*3.14;

	//caso a nave oponente precise mudar de direção
	if(traçadoPista[fase][oponenteLadrilhoX][oponenteLadrilhoY]==4)anguloOponente=9;
	if(traçadoPista[fase][oponenteLadrilhoX][oponenteLadrilhoY]==2)anguloOponente=18;
	if(traçadoPista[fase][oponenteLadrilhoX][oponenteLadrilhoY]==3)anguloOponente=27;
	if(traçadoPista[fase][oponenteLadrilhoX][oponenteLadrilhoY]==1)anguloOponente=0;

	//desenha a nave oponente
	document.getElementById('oponente').src="assets/Oponentes/"+oponenteAleatorio+"/"+anguloOponente+'.png';
	document.getElementById('oponente').style.top=(posiçãoNaveX-posiçãoOponenteX+234)+'px';
	document.getElementById('oponente').style.left=(posiçãoNaveY-posiçãoOponenteY+260)+'px';

	//caso a outra nave termine antes
	if(oponenteLadrilhoX==posiçãoFinalLadrilhoX[fase]&&oponenteLadrilhoY==posiçãoFinalLadrilhoY[fase]){
		alert('A nave oponente chegou ao final antes de você !!!');
		init();
	}

	//caso o user esteja pressionado a tecla esq ou dir
	if(btnEsqPressionado)angulo=(angulo+35)%36;
	if(btnDirPressionado)angulo=(angulo+1)%36;

	//desenha a navinha no centro da tela no angulo correto
	document.getElementById('nave').src="assets/Foguetes/"+angulo+'.png';

	//posiciona a enorme pista atras da nave na posição correta
	document.getElementById('tracado').style.top=posiçãoNaveX+'px';
	document.getElementById('tracado').style.left=posiçãoNaveY+'px';

	//colisão entre as naves
	if(parseInt(document.getElementById('oponente').style.top)>194&&parseInt(document.getElementById('oponente').style.top)<274&&parseInt(document.getElementById('oponente').style.left)>220&&parseInt(document.getElementById('oponente').style.left)<300)parado=5;

	//calculo para descobrir em qual casinha/quadrado/ladrilho está a nave do user
	ladrilhoX=Math.ceil((-posiçãoNaveX+64)/200);
	ladrilhoY=Math.ceil((-posiçãoNaveY+100)/200);

	//se tá na pista
	if(ladrilhoX>=0&&ladrilhoY>=0&&ladrilhoX<traçadoPista[fase].length&&ladrilhoY<traçadoPista[fase][0].length&&traçadoPista[fase][ladrilhoX][ladrilhoY]!=0){

		//diminui o tempo penalidade por colisão
		if(parado>0)parado--;

		//atualiza a posição da nave de acordo com o angulo
		else{
			posiçãoNaveX+=fatorDeslocamentoX[angulo]*3.7;
			posiçãoNaveY+=fatorDeslocamentoY[angulo]*3.7;
		}

		//pinta no minimapa a posição atual da navinha
		document.getElementById('ladrilhoMiniMapa'+ladrilhoX+"_"+ladrilhoY).style.background="#666666";
	}

	//se pisou na grama reinicia a fase
	else init();

	//se chegou no fim do percurso
	if(ladrilhoX==posiçãoFinalLadrilhoX[fase]&&ladrilhoY==posiçãoFinalLadrilhoY[fase]){
		alert('Você venceu !\n\nZerou essa fase !!!');
		desenhaPista(fase+1);
	}

	//re-chama a função que desenha o jogo (depois de uns milissegundos)
	setTimeout('gameLoop();',58-parseInt(tempo++/40));
}

//desenha a enorme pista que se move por debaixo da navinha
function desenhaPista(f){
	fase=f%3;
	htm="<img id='nave'><img id='oponente'><div id='menuLateral'>";
	for(x=0;x<3;x++)htm+="<input class='itemMenu' onclick=\"desenhaPista("+x+");\" type=radio"+(fase==x?" checked":"")+"><br>";
	htm+="</div><table cellpadding='0' cellspacing='0' id='tracado'><tr>";
	for(x=0;x<traçadoPista[fase].length;x++){
		for(y=0;y<traçadoPista[fase][x].length;y++)
			if(traçadoPista[fase][x][y]!=0)htm+="<td class='ladrilho'><img src=assets/Pistas/"+traçadoPista[fase][x][y]+".png></td>";
			else htm+="<td class='ladrilho'> </td>";
		htm+="</tr><tr>";
	}
	document.body.innerHTML=htm+"</tr></table><div id='miniMapa'></div>";

	//inicializa as variaveis para o gameplay que reinicia agora
	init();
}

//quando o user clica sobre o minimapa
function ocultaMiniMapa(){
	document.getElementById('miniMapa').style.display='none';
	document.body.innerHTML+="<img src=assets/Pistas/1.png id='btnMiniMapa' onclick='desenhaPista(fase);'>";
}

Rocket Attack

Faça o download e veja como o jogo Rocket Attack ficou legal.