Codificando um jogo de carrinho

[download id=”467″]

Olá galera do MundoJs

Vamos a mais um tutorial sobre javascript e games !
Desta vez algo um pouco mais avançado.
Se você está começando agora é melhor tentar antes esse tutorial e esse aqui também.

Este artigo mostra uma maneira de fazer um jogo de carrinho em javascript sem nenhuma imagem.

Para começar vamos desenhar o carrinho com HTML5 e Css:

<div style='position:relative; z-index:2; top:254px; left:254px; width:20px; height:40px; background-color:#000000; border-radius:4px;'>
  <div style='width:10px; height:4px; background-color:#000000; border:5px solid #ff4444; border-top:none; border-bottom:none;'></div>
  <div style='width:14px; height:20px; background-color:#999999; border:3px solid #000000;'></div>
</div>

Este carrinho ficará no meio da tela.
A pista irá se mover sob o carrinho.

Vamos desenhar a pista num <canvas>

<canvas id=canvas width=460 height=460 style='background-color:#ffffff; border:4px solid #497894; border-radius:10px;'></canvas>
<script>
  ctx = document.getElementById("canvas").getContext("2d");
  ctx.fillStyle = "#385383";
  ctx.fillRect(200, 200, 200, 200);
</script>

Vamos fazer esta pista se mover sob o carrinho com a função setTimeout atualizando a posição:

<div style='position:relative; z-index:2; top:254px; left:254px; width:20px; height:40px; background-color:#000000; border-radius:4px;'>
  <div style='width:10px; height:4px; background-color:#000000; border:5px solid #ff4444; border-top:none; border-bottom:none;'></div>
  <div style='width:14px; height:20px; background-color:#999999; border:3px solid #000000;'></div>
</div>
<canvas id=canvas width=460 height=460 style='background-color:#ffffff; border:4px solid #497894; border-radius:10px;'></canvas>
<script>
  ctx = document.getElementById("canvas").getContext("2d");
  x = 10;
  function move() {
    ctx.fillStyle = "#9aba9a";
    ctx.fillRect(0, 0, 460, 460);
    ctx.fillStyle = "#385383";
    x = x + 10;
    if (x > 300) x = -400;
    ctx.fillRect(200, 200 + x, 200, 200);
    setTimeout('move()', 100);
  }
  move();
</script>

O próximo passo é centralizar tudo usando a tag <center>

Depois disto interceptar o pressionamento das teclas com o atributo onKeydown

<!doctype html>
<html>
<title>Jogo de Corrida</title>

<body onKeyDown="vira(event.keyCode);" bgcolor=#e1e1e1>
  <br>
  <center>
    <div id=carro>
      <div style='position:relative; z-index:2; top:254px; width:20px; height:40px; background-color:#000000; border-radius:4px;'>
        <div style='width:10px; height:4px; background-color:#000000; border:5px solid #ff4444; border-top:none; border-bottom:none;'></div>
        <div style='width:14px; height:20px; background-color:#999999; border:3px solid #000000;'></div>
      </div>
    </div>
    <canvas id=canvas width=460 height=460 style='background-color:#ffffff; border:4px solid #497894; border-radius:10px;'></canvas>
  </center>
</body>
<script>
  ctx = document.getElementById("canvas").getContext("2d");
  x = 10;
  function move() {
    ctx.fillStyle = "#9aba9a";
    ctx.fillRect(0, 0, 460, 460);
    ctx.fillStyle = "#385383";
    x = x + 10;
    if (x > 300) x = -400;
    ctx.fillRect(200, 200 + x, 200, 200);
    setTimeout('move()', 100);
  }
  move();
  function vira(k) {
    alert(k);
  }
</script>
</html>

A função ‘vira()’ é executada quando o usuário pressiona qualquer tecla.
Com isso podemos descobrir o código das teclas direcionais.

O próximo passo é fazer o carro rotacionar com o comando <body onKeyDown>

<!doctype html>
<html>
<title>Jogo de Corrida</title>

<body onKeyDown="vira(event.keyCode);" bgcolor=#e1e1e1>
  <br>
  <center>
    <div id=carro>
      <div style='position:relative; z-index:2; top:254px; width:20px; height:40px; background-color:#000000; border-radius:4px; transform:rotate(180deg);'>
        <div style='width:10px; height:4px; background-color:#000000; border:5px solid #ff4444; border-top:none; border-bottom:none;'></div>
        <div style='width:14px; height:20px; background-color:#999999; border:3px solid #000000;'></div>
      </div>
    </div>
    <canvas id=canvas width=460 height=460 style='background-color:#ffffff; border:4px solid #497894; border-radius:10px;'></canvas>
  </center>
</body>
<script>
  ctx = document.getElementById("canvas").getContext("2d");
  x = 10;
  function move() {
    ctx.fillStyle = "#9aba9a";
    ctx.fillRect(0, 0, 460, 460);
    ctx.fillStyle = "#385383";
    x = x + 10;
    if (x > 300) x = -400;
    ctx.fillRect(200, 200 + x, 200, 200);
    setTimeout('move()', 100);
  }
  move();
  angulo = 18;
  function vira(k) {
    //alert(k);
    if (k == 37) angulo = (angulo + 35) % 36;
    if (k == 39) angulo = (angulo + 1) % 36;
    document.getElementById('carro').innerHTML = "<div style='position:relative; z-index:2; top:254px; width:20px; height:40px; background-color:#000000; border-radius:4px; transform:rotate(" + angulo + "0deg);'><div style='width:10px; height:4px; background-color:#000000; border:5px solid #ff4444; border-top:none; border-bottom:none;'></div><div style='width:14px; height:20px; background-color:#999999; border:3px solid #000000;'></div></div>";
  }
</script>
</html>

Repare que o angulo começa em 18.
O carro rotacionado 180 graus.
Apontado pra baixo.

’37’ e ’39’ são os códigos das teclas ‘esq’ e ‘dir’ do teclado.

Quando ‘esq’ é apertado o valor do angulo aumenta 35.
Como é sempre o resto da divisão por 36… nunca fica maior que 35.
Praticamente (angulo+35)%36 significa angulo-1.

Esse é o movimento básico do carrinho!

Mas tem uns detalhes a mais.

Enquanto o usuário manter a tecla pressionada o carro tem que ficar girando.
Isso complica um pouco porque o sistema operacional dá uma margem… um intervalo… um delay… quando user pressiona.

Para contornar essa situação vamos usar ‘onkeydown’ e ‘onkeyup’.
Mais duas variáveis ‘esq’ e ‘dir’.

E vamos colocar a atualização da variável angulo, e o desenho do carro, dentro da função ‘move()’

<!doctype html>
<html>
<title>Jogo de Corrida</title>

<body onKeyDown="vira(event.keyCode);" onKeyUp="para(event.keyCode);" bgcolor=#e1e1e1>
  <br>
  <center>
    <div id=carro></div>
    <canvas id=canvas width=460 height=460 style='background-color:#ffffff; border:4px solid #497894; border-radius:10px;'></canvas>
  </center>
</body>
<script>
  ctx = document.getElementById("canvas").getContext("2d");
  x = 10;
  angulo = 18;
  esq = false;
  dir = false;
  function vira(k) {
    if (k == 37) esq = true;
    if (k == 39) dir = true;
  }
  function para(k) {
    esq = false;
    dir = false;
  }
  function move() {
    if (esq) angulo = (angulo + 35) % 36;
    if (dir) angulo = (angulo + 1) % 36;
    document.getElementById('carro').innerHTML = "<div style='position:relative; z-index:2; top:254px; width:20px; height:40px; background-color:#000000; border-radius:4px; transform:rotate(" + angulo + "0deg);'><div style='width:10px; height:4px; background-color:#000000; border:5px solid #ff4444; border-top:none; border-bottom:none;'></div><div style='width:14px; height:20px; background-color:#999999; border:3px solid #000000;'></div></div>";
    ctx.fillStyle = "#9aba9a";
    ctx.fillRect(0, 0, 460, 460);
    ctx.fillStyle = "#385383";
    x = x - 10;
    if (x < -400) x = 460;
    ctx.fillRect(200, 200 + x, 200, 200);
    setTimeout('move()', 50);
  }
  move();
</script>
</html>

Agora começa a parte complicada!
Fazer o carro se mover em relação à pista.

Para isso vamos usar umas variáveis ‘fatorx’ e ‘fatory’.
Elas vão definir o deslocamento do carro em relação a pista… no eixo x e no eixo y.

Por exemplo… quando o carro estiver inclinado 30 graus ele irá se deslocar 6 pixels no eixo x e -3 pixels no eixo y…

fatorx=[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];
fatory=[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];
<!doctype html>
<html>
<title>Jogo de Corrida</title>

<body onKeyDown="vira(event.keyCode);" onKeyUp="para(event.keyCode);" bgcolor=#e1e1e1>
  <br>
  <center>
    <div id=carro></div>
    <canvas id=canvas width=460 height=460 style='background-color:#ffffff; border:4px solid #497894; border-radius:10px;'></canvas>
  </center>
</body>
<script>
  ctx = document.getElementById("canvas").getContext("2d");
  fatorx = [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];
  fatory = [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];
  px = 10;
  py = 10;
  angulo = 18;
  esq = false;
  dir = false;
  function vira(k) {
    if (k == 37) esq = true;
    if (k == 39) dir = true;
  }
  function para(k) {
    esq = false;
    dir = false;
  }
  function move() {
    if (esq) angulo = (angulo + 35) % 36;
    if (dir) angulo = (angulo + 1) % 36;
    document.getElementById('carro').innerHTML = "<div style='position:relative; z-index:2; top:254px; width:20px; height:40px; background-color:#000000; border-radius:4px; transform:rotate(" + angulo + "0deg);'><div style='width:10px; height:4px; background-color:#000000; border:5px solid #ff4444; border-top:none; border-bottom:none;'></div><div style='width:14px; height:20px; background-color:#999999; border:3px solid #000000;'></div></div>";
    ctx.fillStyle = "#9aba9a";
    ctx.fillRect(0, 0, 460, 460);

    px += fatorx[angulo] * 3.7;
    py += fatory[angulo] * 3.7;

    ctx.fillStyle = "#385383";
    ctx.fillRect((200) + py + 38, (200) + px + 28, 200, 200);

    setTimeout('move()', 75);
  }
  move();
</script>
</html>

Agora já temos um carro completamente dirigível !!!
Uhu!!!

Agora vamos à pista.

Vamos criar um ‘array de arrays’ com zeros representando grama e um representando asfalto.

<!doctype html>
<html>
<title>Jogo de Corrida</title>

<body onKeyDown="vira(event.keyCode);" onKeyUp="para(event.keyCode);" bgcolor=#e1e1e1>
  <br>
  <center>
    <div id=carro></div>
    <canvas id=canvas width=460 height=460 style='background-color:#ffffff; border:4px solid #497894; border-radius:10px;'></canvas>
  </center>
</body>
<script>
  ctx = document.getElementById("canvas").getContext("2d");
  fatorx = [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];
  fatory = [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];
  pista = [
    [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1],
    [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1],
    [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1],
    [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1],
    [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1],
    [1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1],
  ];
  px = 10;
  py = 10;
  angulo = 18;
  esq = false;
  dir = false;
  function vira(k) {
    if (k == 37) esq = true;
    if (k == 39) dir = true;
  }
  function para(k) {
    esq = false;
    dir = false;
  }
  function move() {
    if (esq) angulo = (angulo + 35) % 36;
    if (dir) angulo = (angulo + 1) % 36;
    document.getElementById('carro').innerHTML = "<div style='position:relative; z-index:2; top:254px; width:20px; height:40px; background-color:#000000; border-radius:4px; transform:rotate(" + angulo + "0deg);'><div style='width:10px; height:4px; background-color:#000000; border:5px solid #ff4444; border-top:none; border-bottom:none;'></div><div style='width:14px; height:20px; background-color:#999999; border:3px solid #000000;'></div></div>";
    ctx.fillStyle = "#9aba9a";
    ctx.fillRect(0, 0, 460, 460);
    px += fatorx[angulo] * 3.7;
    py += fatory[angulo] * 3.7;
    ctx.fillStyle = "#385383";
    for (x = 0; x < pista.length; x++)for (y = 0; y < pista[x].length; y++)if (pista[x][y] != 0) ctx.fillRect((200 * y) + py + 38, (200 * x) + px + 28, 200, 200);
    setTimeout('move()', 75);
  }
  move();
</script>
</html>

A linha 48 desenha a pista inteira com os ‘for’ e os parâmetros em ‘fillrect’…

Um próximo passo pode ser fazer o carro diminuir a velocidade quando está sobre a grama!

Fazer outras fases…

Fazer a velocidade ir aumentado.

Usar imagens para o carro. Imagens para a pista. pngs transparentes.

‘O céu é o limite.’

Dá para melhorar bem.

Essa é só uma simples versão de 53 linhas

Comparando JavaScript

Primeiro vou comparar JavaScript com linguagens que não são derivadas da linguagem C

 

JavaScript x Pascal

Pascal foi muito bom na época do Delphi7. Era muito integrado com o Windows. Naquela época o JavaScript estava começando.

O problema é que Delphi é praticamente só para Windows. Delphi ficou pra trás por causa da evolução dos browsers.

De certa maneira código Pascal/Delphi é muito bom pois permite ao programador acessar o hardware mais diretamente que js, mas, de certa maneira, Pascal perdeu a briga por causa da ‘portabilidade’ (que era e ainda é a vantagem dos browsers).

Um código escrito em JavaScript para browser roda no Windows, no Linux, no mac, no android… Pascal se tornou engessado.

Para alguns casos ainda vale a pena, mas JavaScript está muito mais acessível.

 

JavaScript x Python

Python é relativamente moderno. Python é uma linguagem interpretada (não compilada) assim como JavaScript. E isso parece ser uma tendência.

Escrever código JavaScript é ligeiramente mais fácil que escrever código em Python.

Em questão de portabilidade JavaScript ganha de longe porque todo dispositivo aceita. Python precisa ser instalado na maioria das vezes.

Em algumas vezes funciona como linguagem server-side, e nesses casos a performance de Python é comparável com a do JavaScript. Talvez Python até ganhe essa disputa.

Mas não ganha a guerra.

 

JavaScript x Asp (Vbscript)

Asp era uma opção. Existia a ‘browser wars’ e também existia a disputa entre PHP e Asp. Entre mySQL e SQL server. Entre Windows server e l.a.m.p.

Parece que isso evoluiu. Ouvi falar dos azure. Ouvi sobre os .net

Parece que ser parceiro da Microsoft tem suas vantagens. Tenho a impressão que existe um suporte ao consumidor. Quem continua investindo em Asp recebe junto no pacote acessória.

Mas de certo modo cai no mesmo buraco que o Delphi: faz software apenas para Windows.

Existe a opção Asp Windows-server, mas considero que a concorrência está na frente.

 

JavaScript x Assembly

Assembly parece ser a mais difícil de escrever. E parece que é a que dá ao programador maior domínio sobre o hardware. Em Assembly dá para fazer coisas que em JavaScript não dá.

Mas por ser tão difícil perde a disputa. E a questão da portabilidade é ainda mais severa. Parece que determinado código Assembly que funciona em um equipamento não funciona em outro determinado equipamento.

Por isso criaram as outras linguagens… o programador escreve o source em linguagem de auto nível e depois o compilador de cada máquina gera o Assembly específico.

 

JavaScript x HTML

HTML é uma linguagem ligada ao js. Na forma mais usual o JavaScript serve para alterar o HTML.

Mas o HTML não aceita instruções como o JavaScript. Html é uma linguagem de marcação.

 

JavaScript x CSS

Css é moderno. É a linguagem irmã-menor do trio: HTML, JavaScript e CSS.

É possível criar belas formas e animações interessantes com CSS, mas seu potencial é alcançado na junção com js.

 

JavaScript x SQL

Sql é uma linguagem tradicional. A história é que antigamente cada desenvolvedor armazenava os dados seguindo seu próprio padrão. Em um determinado momento decidiram facilitar e criaram o padrão SQL. A partir daí surgiu uma camada. Se antes o software era uma peça inteira, depois disso se dividiu em questões relativas a armazenagem de dados e questões relativas a como apresentar dados ao usuário e permitir que ele os edite.

SQL tem essa limitação. Não é para efeitos visuais. Serve por debaixo dos panos.


Agora vamos comprar JavaScript com linguagens que são derivadas da linguagem C

 

JavaScript x c

A linguagem c hoje em dia é referencial.

As outras linguagens são influenciadas por ela.

Ela é muito utilizada no ensino de linguagens de programação.

A sintaxe da linguagem C é a mesma da linguagem js.

Considero que JavaScript é descendente direta de C. A descendente mais famosa.

 

JavaScript x Java

Java também é descendente de C. A descendente mais certinha.

Funciona como linguagem desktop, apesar de que eu não recomendo. E também funciona como server-side, mas eu também não recomendo. Para mim a gloria do Java é ser a linguagem oficial do android.

São duas linguagens em níveis diferentes. Apesar de serem parecidas e terem o nome parecido.

Java é bem mais difícil porque mostra ao programador o hardware.

 

JavaScript x PHP

PHP já reinou absoluto no server-side. Apesar da concorrência com a Microsoft.

Agora concorre com nodejs, Python, Java e Microsoft. E outras.

Também é descendente de C.

É a linguagem C com o símbolo de dólar na frente dos nomes das variáveis.

Eu ainda vivo na época do PHP…

Gosto de PHP server-side e JavaScript client-side


E agora vou comparar JavaScript com ela mesma

 

JavaScript x JavaScript server-side

A linguagem JavaScript é muito permissiva. O programador pode escrever a mesma instrução de várias maneiras diferentes. Nada é tipado.

Isso facilita muito pra quem tá começando.

E oferece a possibilidade de o desenvolvedor fazer de várias maneiras.

Mas nem sempre isso é vantagem.

Considero que o server deve ser rápido na sua simples tarefa de receber a ‘requisição’, buscar como ‘resolvê-la’ e entregar o HTML para o browser.

E a permissividade pode acarretar perda de performance pelo tempo do server ‘entender’ um comando e pelo programador optar por um paradigma e abrir mão de outros…

Como disse acima: gosto de PHP.

 

JavaScript x JavaScript unity

A unity permite que o usuário codifique em JavaScript. Isso é bom pois facilita para o usuário.

Em relação ao JavaScript tradicional, a diferença está no interpretador.

No js tradicional é o browser que executa os comandos, no caso da unity o compilador lida com outros objetos.

Nos dois casos, escrever código JavaScript é abrir mão de lidar diretamente com o hardware.

Para finalizar afirmo que JavaScript é minha linguagem de programação favorita. Por ser executada em qualquer dispositivo.

Como fazer um jogo em JavaScript com a tag canvas

[download id=”396″]

Esse tutorial apresenta uma maneira de desenvolver o jogo pong. Um jogo básico e simples.
Vamos começar criando um arquivo em branco chamado jogo.htm. Nesse arquivo vamos digitar o código:

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

Vamos apagar a frase e colocar o elemento canvas

<canvas></canvas>

Se você 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>

Para o jogo ficar de um jeito legal vamos colocar o canvas no meio da tela e dar o tamanho 400x450px
O motivo que me levou a usar o elemento canvas é que ele possibilita desenhar na tela codificando… escrever ‘desenhe uma linha azul;’ ou ‘desenhe um quadrado no canto’
Os primeiros jogos eletrônicos eram em modo texto. Em seguida eram em blocos quadrados. Depois eram desenhados através 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’

Quando fiz esse jogo no canvas pela primeira vez em 2010 eu estava acompanhando o surgimento do html5 e li sobre o canvas e sobre como era possível desenhar nele. O jogo foi resultado de testes que começaram com a pergunta: ‘Como eu desenho uma bola nesse canvas?’
Eu pesquisei… em vários sites e tutoriais… inclusive no site do w3c e w3schools

Para desenhar no canvas eu preciso de um ‘context’
Para isso eu dou um id pro canvas que criei… e uso 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>

Para 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();

Recomendo que vc entenda esses parâmetros.

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 parâmetros 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();
canvas.fillStyle='#ffffff'; 
canvas.fillRect(0,0,400,450);

Para 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>
barrax=150;
canvas.fillStyle='#000000'; 
canvas.fillRect(barrax,430,100,20);

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

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

E vamos escrever a função movebarra
Inicialmente vamos por um alert para 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)barrax-=40;
    if(tecla==39)barrax+=40;
}

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

O código até aqui fica:

<!doctype html>
<html>
<body onkeyDown='movebarra(event.which);'>
<center><canvas id=canvas width=400 height=450 style='border:1px solid #4a4a4a;'></canvas></center>
<script>
canvas=document.getElementById('canvas').getContext('2d');
x=20;
y=200;
tamanho=10;
dx=2;
dy=2;
barrax=150;
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='#000000';
    canvas.fillRect(barrax,430,100,20);
    canvas.fillStyle='#ff0000';
    canvas.beginPath();
    canvas.arc(x,y,tamanho,0,Math.PI*2,false);
    canvas.fill();
    if(y>430-tamanho)
    {	
        var dif=x-barrax;
        if(dif>-10&&dif<110)
        {	dy*=-1;
            if(dif>-10&&dif<15)dx=-3;
            if(dif>=15&&dif<50)dx=-2;
            if(dif>=50&&dif<85)dx=2;
            if(dif>=85&&dif<110)dx=3;
            y=430-tamanho;
        }
    }
    if(y<450-tamanho)setTimeout('anda();',10);
    else alert('Fim de jogo');
}
anda();
function movebarra(tecla)
{	
    /*alert(tecla);*/
    if(tecla==37)barrax-=40;
    if(tecla==39)barrax+=40;
}
</script>
</body>
</html>

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

 

  • A posição x do bloco
  • A posição y
  • Se o bloco deve ser exibido (começa com true e fica false assim que a bola atingir)
bloco=[10,20,true];
if(bloco[2])
{	
    canvas.fillStyle='#0000ff';
    canvas.fillRect(bloco[0],bloco[1],50,20);
}
if(bloco[2])
{	
    var dif=y-bloco[1]-tamanho;
    if((dy<0&&(dif>0&&dif<20))||(dy>0&&(dif<0&&dif>-20)))
    {	if(x>bloco[0]&&x<bloco[0]+50)
        {	dy*=-1;
            bloco[2]=false;
        }
    }
}

Por enquanto fizemos o jogo funcionar com um bloco
Vamos transformar em 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])
{	
    var dif=y-blocos[c][1]-tamanho;
    if((dy<0&&(dif>0&&dif<20))||(dy>0&&(dif<0&&dif>-20)))
    {	if(x>blocos[c][0]&&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);
}

O código completo fica:

<!doctype html>
<html>
<body onkeyDown='movebarra(event.which);'>
<center><canvas id=canvas width=400 height=450 style='border:1px solid #4a4a4a;'></canvas></center>
<script>
canvas=document.getElementById('canvas').getContext('2d');
blocos=[];
for(x=0;x<8;x++)for(y=0;y<5;y++)blocos.push([x*50,y*20,true]);
x=20;
y=200;
tamanho=10;
dx=2;
dy=2;
barrax=150;
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='#000000';
    canvas.fillRect(barrax,430,100,20);
    canvas.fillStyle='#ff0000';
    canvas.beginPath();
    canvas.arc(x,y,tamanho,0,Math.PI*2,false);
    canvas.fill();
    for(c=0;c<blocos.length;c++)if(blocos[c][2])
    {	
        canvas.fillStyle='#0000ff';
        canvas.fillRect(blocos[c][0],blocos[c][1],50,20);
    }
    for(c=0;c<blocos.length;c++)if(blocos[c][2])
    {	
        var dif=y-blocos[c][1]-tamanho;
        if((dy<0&&(dif>0&&dif<20))||(dy>0&&(dif<0&&dif>-20)))
        {	
            if(x>blocos[c][0]&&x<blocos[c][0]+50)
            {	blocos[c][2]=false;
                dy*=-1;
            }
        }
    }
    if(y>430-tamanho)
    {	
        var dif=x-barrax;
        if(dif>-10&&dif<110)
        {	
            dy*=-1;
            if(dif>-10&&dif<15)dx=-3;
            if(dif>=15&&dif<50)dx=-2;
            if(dif>=50&&dif<85)dx=2;
            if(dif>=85&&dif<110)dx=3;
            y=430-tamanho;
        }
    }
    if(y<450-tamanho)setTimeout('anda();',10);
    else alert('Fim de jogo');
}
anda();
function movebarra(tecla)
{	
    /*alert(tecla);*/
    if(tecla==37)barrax-=40;
    if(tecla==39)barrax+=40;
}
</script>
</body>
</html>

Como fazer um jogo em JavaScript

[download id=”285″]

Olá Pessoal do MundoJs !

Esse é um artigo/tutorial sobre mecanismos básicos de jogos em javascript

Será apresentada uma maneira bem básica de como fazer um jogo da cobrinha em javascript. É um jogo para ser jogado no browser/navegador (chrome/firefox/explorer) mas não funciona em tablets e celulares porque precisa do teclado…

Vamos começar criando um arquivo .html em branco. E logo em seguida escrever um pouco de html:

<html>
<body>
    <div id=principal></div>
    <script>
        document.getElementById('principal').innerHTML='Daqui surge o jogo';
    </script>
</body>
</html>

Até aqui sem maiores surpresas… um simples arquivo sem muita complicação.

Logo em seguida vamos criar o tabuleiro por onde a cobra irá se movimentar:

<html>
<body>
    <div id=principal></div>
    <script>
    tabuleiro="<table align=center border=1>";
    for(x=0;x<10;x++){
        tabuleiro+="<tr>";
        for(y=0;y<10;y++)
            tabuleiro+="<td>"+x+"_"+y+"</td>";
        tabuleiro+="</tr>";
    }
    document.getElementById('principal').innerHTML=tabuleiro+"</table>";
    </script>
</body>
</html>

Vamos dar um id para cada celula do tabuleiro:

for(y=0;y<10;y++){
    tabuleiro+="<td id=td"+x+"_"+y+" style='width:30px; height:30px;'> </td>";
}

Vamos ‘pintar’ uma celula do tabuleiro:

document.getElementById('td3_3').style.background="#333333";

Vamos criar uma variavel cobra[] que armazena a coordenada (x,y) da cobra:

cobra=[5,0];
document.getElementById('td'+cobra[0]+'_'+cobra[1]).style.background="#333333";

Vamos fazer a cobra ‘andar’ com a função ‘setTimeout’:

function anda(){
    cobra[1]++;
    document.getElementById('td'+cobra[0]+'_'+cobra[1]).style.background="#333333";
    setTimeout('anda()',300);
}
anda();

Essa função setTimeout é a base do movimento em javascript. Existem alternativas mas essa é nativa e tem vantagens…

E vamos ‘apagar’ o rastro da cobrinha:

function anda(){
    document.getElementById('td'+cobra[0]+'_'+cobra[1]).style.background="#ffffff";
    cobra[1]++;
}

Vamos ‘interceptar/interpretar’ a tecla que o usuário aperta no teclado:

<body onKeyDown="pegadirecao(event.keyCode);">
function pegadirecao(tecla){
    alert(tecla);
}

Vamos criar uma variavel direcao que armazena/determina pra onde a cobra deve se mover:

direcao=2;
function pegadirecao(tecla){
    /*alert(tecla);*/
    if(tecla==37)direcao=0;
    if(tecla==38)direcao=1;
    if(tecla==39)direcao=2;
    if(tecla==40)direcao=3;
}

E dentro da função anda

if(direcao==0)cobra[1]--;
if(direcao==1)cobra[0]--;
if(direcao==2)cobra[1]++;
if(direcao==3)cobra[0]++;

vamos criar a maçã:

mx=parseInt(Math.random()*10);
my=parseInt(Math.random()*10);

E na função ‘anda()’

document.getElementById('td'+mx+'_'+my).style.background="#ff3333";

Vamos fazer a maçã ser gerada novamente:

if(mx==cobra[0]&&my==cobra[1]){
    mx=parseInt(Math.random()*10);
    my=parseInt(Math.random()*10);
    cobra[cobra.length]=[10,10];
}

Agora vem a parte mais sofisticada do jogo. Vamos transformar a variável cobra de um array para um array de arrays. Até agora a variavel cobra armazenava um ponto. A partir daqui essa variavel armazenará um array de pontos…

cobra=[[5,0]];
function anda(){
    document.getElementById('td'+cobra[cobra.length-1][0]+'_'+cobra[cobra.length-1][1]).style.background="#ffffff";
    if(mx==cobra[cobra.length-1][0]&&my==cobra[cobra.length-1][1]){
        mx=parseInt(Math.random()*10);
        my=parseInt(Math.random()*10);
        cobra[cobra.length]=[10,10];
    }
    if(direcao==0)cobra[0][1]--;
    if(direcao==1)cobra[0][0]--;
    if(direcao==2)cobra[0][1]++;
    if(direcao==3)cobra[0][0]++;
    document.getElementById('td'+cobra[0][0]+'_'+cobra[0][1]).style.background="#333333";
    document.getElementById('td'+mx+'_'+my).style.background="#ff3333";
    setTimeout('anda()',300);
}

Para fazer a cobra se movimentar devemos passar os valores de cada coordenada de cada ‘gomo’ da cobra para o ‘gomo de traz’:

for(x=cobra.length-1;x>0;x--){
    cobra[x][0]=cobra[x-1][0];
    cobra[x][1]=cobra[x-1][1];
}

Agora só falta fazer função que executará quando a cobra ‘morrer’:

vivo=true;
if(vivo)setTimeout('anda()',300);
else alert('Fim de jogo');
for(x=1;x<cobra.length;x++){
    if(cobra[0][0]==cobra[x][0]&&cobra[0][1]==cobra[x][1])vivo=false;
    if(cobra[0][0]<0||cobra[0][1]<0||cobra[0][0]>9||cobra[0][1]>9)vivo=false;
}

O código completo fica:

<html>
<body onKeyDown="pegadirecao(event.keyCode);">
<div id=principal></div>
<script>
    tabuleiro="<table align=center border=1>";
    for(x=0;x<10;x++){
        tabuleiro+="<tr>";
        for(y=0;y<10;y++)
            tabuleiro+="<td id=td"+x+"_"+y+" style='width:30px; height:30px;'> </td>";
        tabuleiro+="</tr>";
    }
    document.getElementById('principal').innerHTML=tabuleiro+"</table>";
    cobra=[[5,0]];
    direcao=2;
    mx=parseInt(Math.random()*10);
    my=parseInt(Math.random()*10);
    vivo=true;
    function anda(){
        document.getElementById('td'+cobra[cobra.length-1][0]+'_'+cobra[cobra.length-1][1]).style.background="#ffffff";
        if(mx==cobra[cobra.length-1][0]&&my==cobra[cobra.length-1][1]){
            mx=parseInt(Math.random()*10);
            my=parseInt(Math.random()*10);
            cobra[cobra.length]=[10,10];
        }
        for(x=cobra.length-1;x>0;x--){
            cobra[x][0]=cobra[x-1][0];
            cobra[x][1]=cobra[x-1][1];
        }
        if(direcao==0)cobra[0][1]--;
        if(direcao==1)cobra[0][0]--;
        if(direcao==2)cobra[0][1]++;
        if(direcao==3)cobra[0][0]++;
        for(x=1;x<cobra.length;x++)if(cobra[0][0]==cobra[x][0]&&cobra[0][1]==cobra[x][1])vivo=false;
        if(cobra[0][0]<0||cobra[0][1]<0||cobra[0][0]>9||cobra[0][1]>9)vivo=false;
        document.getElementById('td'+cobra[0][0]+'_'+cobra[0][1]).style.background="#333333";
        document.getElementById('td'+mx+'_'+my).style.background="#ff3333";
        if(vivo)setTimeout('anda()',300);
        else alert('Fim de jogo');
    }
    anda();
    function pegadirecao(tecla){
        /*alert(tecla);*/
        if(tecla==37)direcao=0;
        if(tecla==38)direcao=1;
        if(tecla==39)direcao=2;
        if(tecla==40)direcao=3;
    }
</script>
</body>
</html>