Sei sulla pagina 1di 13

www.indiegamerbrasil.

com Tutorial bsico de games Lio 1

IndieGamerBrasil.com
Tutorial bsico de games
(c) 2013 by Cleuton Sampaio
Lio 1: objetos, tempo e movimento

Voc tem a liberdade de:

Compartilhar copiar, distribuir e transmitir a obra.

Com as seguintes condies:

Atribuio Voc deve creditar a obra da forma especificada pelo autor ou licenciante
(mas no de maneira que sugira que estes concedem qualquer aval a voc ou ao seu uso da
obra).

Uso no comercial Voc no pode usar esta obra para fins comerciais.

Vedada a criao de obras derivadas Voc no pode alterar, transformar ou criar em


cima desta obra.

Leia mais sobre esta licena em: http://creativecommons.org/licenses/by-nc-nd/3.0/br/legalcode.

www.indiegamerbrasil.com Tutorial bsico de games Pgina: 1 de: 13

www.indiegamerbrasil.com Tutorial bsico de games Lio 1

Lio 1: objetos, tempo e movimento


Nesta lio, vamos criar um jogo bsico, contendo um objeto, que se movimenta quando acionamos
as teclas correspondentes. Eis a imagem:

Calma! Eu sei que decepcionante... Mas toda longa jornada tem que comear com um passo. E
este o nosso primeiro passo.
Os arquivos esto em anexo. A pasta imagens tem as imagens globais do tutorial, e a pasta
scripts tem os scripts, imagens e css desta lio. Para executar, abra o arquivo
scripts/index.html no seu navegador e clique no boto iniciar da pgina. Depois, clique nos
botes Frente, Trs, Direita e Esquerda, para movimentar o objeto (a bola vermelha no
centro da arena).

Imagens
Nosso game ter algumas imagens:

Rua, com caladas e pistas;

Carros diversos;

A pessoa.

Todas as imagens esto dentro de imagens/objetos.odg, que um arquivo gerado pelo LibreOffice
Draw (). Voc pode selecionar e exportar as imagens individuais como png:
www.indiegamerbrasil.com Tutorial bsico de games Pgina: 2 de: 13

www.indiegamerbrasil.com Tutorial bsico de games Lio 1


1. Selecione o(s) objeto(s) a exportar;
2. Abra o menu Arquivo / Exportar;
3. Marque a caixa seleo e mude o tipo para PNG;
Depois, abra a imagem no Gimp e adicione o canal alpha para as transparncias, caso seja
necessrio. Eu j fiz isto para voc, logo, no necessrio fazer isto agora.

Arquivos Javascript e inicializao do game


Os arquivos dentro de scripts/js so arquivos-fonte em Javascript, que devem ser referenciados
pela pgina index.html. Eles contm: funes e classes que vamos utilizar no Game. Eis os
arquivos-fonte:

inicializacao.js: funes de inicializao do game e das variveis de controle;

pessoa.js: implementao da classe Pessoa, que vai gerar o objeto que representa a
pessoa que vai atravessar a rua;

gameloop.js: o gameloop principal, que controla a atualizao do jogo, a funo de


desenho e outras funes auxiliares de controle.

Os arquivos Javascript so referenciados no cdigo da pgina index.html:


<!DOCTYPE html>
<html>
<head>
<!-- Estilos -->
<link rel="stylesheet" type="text/css" href="css/estilo.css"></link>
<!-- Inicializacao -->
<script type="text/javascript" src="js/inicializacao.js"></script>
<!-- GameObjects -->
<script type="text/javascript" src="js/pessoa.js"></script>
<!-- Game loop -->
<script type="text/javascript" src="js/gameloop.js"></script>
</head>
<body onload="inicializa()">
<button onclick="iniciar()">Iniciar</button>
<button onclick="parar()">Parar</button>
<button onclick="frente()">Frente</button>
<button onclick="tras()">Tr&aacute;s</button>
<button onclick="direita()">Direita</button>
<button onclick="esquerda()">Esquerda</button>
<br/>
<div id="conteudo"></div>
</body>
</html>

www.indiegamerbrasil.com Tutorial bsico de games Pgina: 3 de: 13

www.indiegamerbrasil.com Tutorial bsico de games Lio 1


Sempre que um arquivo Javascript (*.js) carregado com o tag <script>, suas funes e
variveis se tornam parte do ambiente de execuo e podem ser invocadas pelos tags HTML, como
neste caso:
<body onload="inicializa()">

O evento onload da pgina acontece quando ela completamente carregada no navegador, logo,
todos os seus elementos foram completamente carregados. Neste caso, estou invocando a funo
inicializa(), que fica no arquivo inicializacao.js:
// inicializacao.js
function inicializa() {
larguraJanela = window.innerWidth;
alturaJanela = window.innerHeight;
// Prepara a "canvas" do game:
conteudo = document.getElementById("conteudo");
// Calcula tamanhos e posiciona a canvas:
var textoCanvas = "<canvas id=\"tela\" " +
" width=\"" + larguraJanela * 0.98 + "\"" +
" height=\"" + alturaJanela * 0.83 + "\"" +
"></canvas>";
conteudo.innerHTML = textoCanvas;
retangulo = {altura : tela.clientHeight, largura : tela.clientWidth};
contexto = tela.getContext("2d");
// Calcula a proporcao metro-tela: 1 metro = 10% da tela
metroPixels = Math.round(tela.clientWidth * 0.10);
retanguloMetros = {altura : tela.clientHeight / metroPixels, largura :
tela.clientWidth / metroPixels};

// Cria o vetor de gameObjects e outras variveis de controle:


gameObjects = new Array();
idGameLoop = null;
tempo = new Date();
velocidadeX = 0.0;
velocidadeY = 0.0;

A funo inicializa() no inicia o game! Isto feito pela funo iniciar(), que invocada ao
clicar no boto iniciar:
<button onclick="iniciar()">Iniciar</button>

A funo inicializa() prepara o ambiente:


1. Calcula e exibe o Canvas dentro do elemento Conteudo;

www.indiegamerbrasil.com Tutorial bsico de games Pgina: 4 de: 13

www.indiegamerbrasil.com Tutorial bsico de games Lio 1


2. Cria referncias para o retngulo do Canvas;
3. Calcula a proporo metro / pixel;
4. Inicializa o vetor de gameobjects;
5. Inicializa algumas variveis de controle.
Estude um pouco a funo inicializar() e anote quais so as variveis globais, utilizadas em outros
scripts.
Em Javascript, uma varivel declarada sem o var considerada como Global e est disponvel
para qualquer outro script.

Tamanho e proporo
Um dos maiores problemas de qualquer game a proporo... Um game tem que executar
independentemente do tamanho da janela. E tudo tem que ficar na mesma proporo. Ns aqui
vamos considerar a unidade metro, informando-a em todas as definies dos gameobjects (altura,
largura, velocidade, posio etc).
Porm, temos que saber quanto vale 1 metro em pixels, o que depende da largura da tela. Ns
consideramos 1 metro como 10% da largura da tela. Assim, se o navegador for maior ou menor, no
importa: a proporo do tamanho e do movimento dos objetos ser a mesma.
Por isto criamos a varivel global metroPixels, dentro da funo inicializar().

O Game loop
O gameloop uma parte importante de qualquer game. Ele responsvel por atualizar o status do
game em cada instante. Para isto, ele precisa:

Calcular a posio dos gameobjects;

Verificar colises e outros eventos;

Renderizar (desenhar) os gameobjects na nova posio.

Ele repetido de tempos em tempos e deve rodar em paralelo com a interface de usurio, pois, caso
contrrio, pode travar o jogo.
www.indiegamerbrasil.com Tutorial bsico de games Pgina: 5 de: 13

www.indiegamerbrasil.com Tutorial bsico de games Lio 1

Existem recursos que permitem usar programao concorrente, como Threads, ou Web Workers,
no HTML 5, porm, no esto disponveis em todos os navegadores, logo, no vamos utiliz-los.
O nosso gameloop fica no arquivo gameloop.js, na funo gameLoop():
function gameLoop() {
// Atualiza o "mundo" do game:
// Tempo decorrido desde a ltima atualizao:
var agora = new Date();
var tempoDecorrido = timeDifference(agora, tempo);
for (var x=0; x < gameObjects.length; x++) {
if (gameObjects[x].ativa) {
updateGO(gameObjects[x], tempoDecorrido);
}
}
// Escala a funcao de desenho para execuo:
setTimeout("desenhar()", 5);
tempo = agora;
}

O que ele faz? Ele calcula quanto tempo se passou desde a sua ltima execuo (em fraes de
segundo), e atualiza todos os gameobjects que esto no vetor global gameObjects (veremos mais
adiante). Para cada gameobject ele invoca a funo updateGO.
Depois de atualizar todos os gameobjects, necessrio desenh-los. Ele coloca a funo
desenhar() para executar em 5 milissegundos, com a funo setTimeout. Por que isso? Bem,
para no travar o thread principal do navegador. Em 5 milissegundos ele vai invocar a funo
desenhar().
claro que este gameloop est incompleto, afinal, apenas a primeira lio...
Como o gameloop iniciado?
Ao clicar o boto iniciar, a funo iniciar(), do arquivo gameloop.js invocada. Veja no
HTML (scripts/index.html):
<button onclick="iniciar()">Iniciar</button>

www.indiegamerbrasil.com Tutorial bsico de games Pgina: 6 de: 13

www.indiegamerbrasil.com Tutorial bsico de games Lio 1


Esta funo assim:
function iniciar() {
// Posiciona a pessoa

pessoa = new Pessoa();


pessoa.centroX = retanguloMetros.largura / 2;
pessoa.centroY = retanguloMetros.altura / 2;
pessoa.imagem = new Image();
pessoa.imagem.src = pessoa.arqImagem;
gameObjects[0] = pessoa;
idGameLoop = window.setInterval("gameLoop()", 50);

O que esta funo faz? Ela deve carregar o cenrio do nvel corrente, se estamos falando em um
game multinveis (a maioria ).
No nosso caso, estamos criando uma Pessoa e colocando-a no centro da arena. Estamos criando
um objeto do tipo Pessoa na memria, e depois colocando uma referncia para ele dentro do
nosso vetor de gameObjects.
A definio da classe Pessoa feita no arquivo pessoa.js:
// pessoa.js
var templatePessoa = {
arqImagem : "images/pessoa.png",
imagem : null,
centroX : 0,
centroY : 0,
velocidadeX : 1.0,
velocidadeY : 1.0,
aceleracaoX : 0.0,
aceleracaoY : 0.0,
altura : 1,
largura : 1,
ativa : true};
function Pessoa() {
this.arqImagem = templatePessoa.arqImagem;
this.imagem = templatePessoa.imagem;
this.centroX = templatePessoa.centroX;
this.centroY = templatePessoa.centroY;
this.velocidadeX = templatePessoa.velocidadeX;
this.velocidadeY = templatePessoa.velocidadeY;
this.aceleracaoX = templatePessoa.aceleracaoX;
this.aceleracaoY = templatePessoa.aceleracaoY;
this.altura = templatePessoa.altura;
this.largura = templatePessoa.largura;
this.ativa = templatePessoa.ativa;
}

www.indiegamerbrasil.com Tutorial bsico de games Pgina: 7 de: 13

www.indiegamerbrasil.com Tutorial bsico de games Lio 1


Usamos um gabarito templatePessoa com valores iniciais a serem colocados na propriedade do
Game Object. A funo Pessoa() define um objeto que contm as propriedades:

arqImagem : nome do arquivo de imagem a ser carregado;

imagem : objeto imagem carregado a partir do arquivo;

centroX : a localizao do objeto, com relao ao eixo x;

centroY : a localizao do objeto, com relao ao eixo y;

velocidadeX : velocidade atual do objeto no eixo x;

velocidadeY : velocidade atual do objeto no eixo y;

aceleracaoX : acelerao atual do objeto no eixo x;

aceleracaoY : acelerao atual do objeto no eixo y;

altura : altura do objeto em metros;

largura : largura do objeto em metros;

ativa : se o objeto est ativo ou no;

O gameloop iniciado com este comando:


idGameLoop = window.setInterval("gameLoop()", 50);

Colocamos a funo gameLoop() para ser invocada a cada 50 milissegundos.


Se o usurio clicar no boto parar, ns cancelamos este agendamento:
function parar() {
window.clearInterval(idGameLoop);
}

Atualizao dos gameobjects


O vetor gameObjects, criado na funo inicializa(), contm os gameobjects que necessitam ser
atualizados a cada novo frame do game.
Todas as vezes que o gameloop executado, uma nova situao do jogo gerada. Como se fosse
uma foto ou quadro, tambm conhecido como frame. Muitos game engines falam em frame
www.indiegamerbrasil.com Tutorial bsico de games Pgina: 8 de: 13

www.indiegamerbrasil.com Tutorial bsico de games Lio 1


rate, que o nmero de quadros gerados por segundo.
Alguns games rodam na taxa de 30 FPS (Frames Per Second). Alguns rodam em 60 FPS. Quanto
maior a taxa, melhor o resultado. Porm, rodar a 60 FPS no para qualquer plataforma. Em nosso
caso, o gameloop roda a cada 50 ms, e o renderloop (a funo desenhar()) roda 5 ms depois. O
clculo simples:
Temos: 1 segundo = 1.000 ms. Ns geramos 1 frame a cada 50 ms, logo, temos 1000 / 50 = 20
frames por segundo. Est bom, para comear, embora ainda resulte em algum lag. Podemos at
diminuir o intervalo do gameloop. Mas vamos deixar isto para depois.
A funo updateGO() atualiza a posio de cada gameobject. Eis o cdigo-fonte
(gameobject.js):
function updateGO(go, intervalo) {
var deslocamentoX = velocidadeX * intervalo;
var deslocamentoY = velocidadeY * intervalo;
go.centroX += deslocamentoX;
go.centroY += deslocamentoY;
}

Esta funo recebe o gameobject (retirado do vetor gameObjects) e o intervalo, em fraes de


segundo. Ento, ela calcula o deslocamento a ser aplicado em cada eixo (x e y), multiplicando a
velocidade atual em cada eixo pela frao de segundo passada. Finalmente, atualiza a posio do
centro do gameobject.
A velocidade sempre em metros por segundo (m/s), ento calculamos o deslocamento
multiplicando a velocidade pela frao de segundo decorrida. Poderamos tambm ter esperado
completar 1 segundo para movimentar.

Desenho dos gameobjects


Se voc conhece HTML 5, deve estar perguntando: Por que ele no desenha os objetos no Canvas,
ao invs de usar imagens? A resposta simples: porque melhor usar imagens!
Todos os games usam imagens. Ns estamos usando um ponto vermelho, mas podemos muito bem
substituir por uma carroa ou por um cachorro, visto de cima. Imagens so melhores do que
desenhos vetoriais, sem dvida. E, se voc acha que o ponto est serrilhado, s diminuir seu
tamanho, ou ento gerar uma imagem com resoluo maior. S que isso no importa agora.

www.indiegamerbrasil.com Tutorial bsico de games Pgina: 9 de: 13

www.indiegamerbrasil.com Tutorial bsico de games Lio 1


A funo desenhar() pega cada gameobject do vetor, calcula o canto superior esquerdo e renderiza
a imagem armazenada. Eis o cdigo-fonte:
function desenhar() {
contexto.clearRect(0,0,tela.width,tela.height);
var tempoDecorrido = timeDifference(new Date(), tempo);
// Desenha os gameObjects:
for (var x=0; x < gameObjects.length; x++) {
var topo = calcularTopo(gameObjects[x]);
var esquerda = calcularEsquerda(gameObjects[x]);
var larguraImagem = gameObjects[x].largura * metroPixels;
var alturaImagem = gameObjects[x].altura * metroPixels;
contexto.drawImage(gameObjects[x].imagem,
esquerda,topo,
larguraImagem,alturaImagem);
}
}

Ns estamos usando a varivel global contexto, que foi criada na funo inicializa():
// Calcula tamanhos e posiciona a canvas:
var textoCanvas = "<canvas id=\"tela\" " +
" width=\"" + larguraJanela * 0.98 + "\"" +
" height=\"" + alturaJanela * 0.83 + "\"" +
"></canvas>";
conteudo.innerHTML = textoCanvas;
retangulo = {altura : tela.clientHeight, largura : tela.clientWidth};
contexto = tela.getContext("2d");

Ns criamos um elemento tela dinamicamente, e pegamos o seu contexto grfico 2d, logo,
podemos usar este contexto para desenhar imagens.
Antes de continuarmos, necessrio explicar qual o sistema de coordenadas de um Canvas. A
origem no canto superior esquerdo, com os valores das ordenadas (eixo y) crescendo para
baixo. Os valores das abscissas normal, crescendo para a direita. meio diferente de um plano
cartesiano normal, onde a origem fica no centro e o valor das ordenadas cresce para cima.

www.indiegamerbrasil.com Tutorial bsico de games Pgina: 10 de: 13

www.indiegamerbrasil.com Tutorial bsico de games Lio 1

Isto muito importante, pois todos os clculos devem considerar a diferena na ordem do eixo y.
Continuando, o mtodo drawImage(), do contexto, espera os seguintes argumentos (existem
outras opes):

Imagem: a imagem a ser desenhada;

X, Y: coordenadas do canto superior esquerdo, onde a imagem dever ser desenhada;

Largura, Altura: largura e altura da imagem (isto faz com que seja esticada ou escalada);

Temos um probleminha: precisamos converter as coordenadas do centro do gameobject em


coordenadas do canto superior esquerdo. para isto que servem as funes: calcularTopo() e
calcularEsquerda(). Elas convertem as coordenadas do centro do objeto em coordenadas de canto
superior esquerdo. Para isto, precisam calcular o tamanho do objeto em pixels.
function calcularTopo(go) {
// Pegamos o meio (Y) e subtramos metade da altura:
// (nao podemos esquecer de converter metro em pixels)
var topo = (go.centroY * metroPixels) - ((go.altura * metroPixels) / 2);
return topo;
}
function calcularEsquerda(go) {
// Pegamos o meio (X) e subtramos metade da largura:
// (nao podemos esquecer de converter metro em pixels)
var esquerda = (go.centroX * metroPixels)
- ((go.largura * metroPixels) / 2);
return esquerda;
}

www.indiegamerbrasil.com Tutorial bsico de games Pgina: 11 de: 13

www.indiegamerbrasil.com Tutorial bsico de games Lio 1

Movimentao do gameobject
Inicialmente, o nosso nico gameobject est parado, pois os valores das variveis globais
velocidadeX e velocidadeY esto zerados.
Depois de clicar no boto iniciar, se o jogador clicar em qualquer um dos botes de movimento,
vamos mudar o valor das velocidades X e Y:
<button
<button
<button
<button

onclick="frente()">Frente</button>
onclick="tras()">Tr&aacute;s</button>
onclick="direita()">Direita</button>
onclick="esquerda()">Esquerda</button>

Eis as funes que alteram o valor das velocidades (gameloop.js):


function tras() {
velocidadeY += 1;
}
function frente() {
velocidadeY -= 1;
}
function direita() {
velocidadeX += 1;
}
function esquerda() {
velocidadeX -= 1;
}

A funo updateGO() utiliza os valores de velocidadeX e velocidadeY para alterar o


deslocamento do gameobject no canvas:
function updateGO(go, intervalo) {
var deslocamentoX = velocidadeX * intervalo;
var deslocamentoY = velocidadeY * intervalo;
go.centroX += deslocamentoX;
go.centroY += deslocamentoY;
}

www.indiegamerbrasil.com Tutorial bsico de games Pgina: 12 de: 13

www.indiegamerbrasil.com Tutorial bsico de games Lio 1

O que est faltando?


Muita coisa!
Para comear, o gameobject no est sendo limitado por nada. Se voc sair da tela, ele some.
preciso limitar seu movimento. Voc sabe fazer isso?
Em segundo lugar, falta o cenrio (a rua), e os carros.
Vamos criar isso nas prximas lies.

www.indiegamerbrasil.com Tutorial bsico de games Pgina: 13 de: 13

Potrebbero piacerti anche