Se você nunca jogou o famoso jogo Snake , levante a mão!
Digo isso, mas suponho que hoje em dia a nova geração talvez nunca tenha ouvido falar deste jogo, que pode parecer um pouco antiquado dadas as possibilidades que os computadores e a Web de hoje oferecem.
E, no entanto, houve um tempo em que o jogo Snake era um jogo em que todos os proprietários de telefones celulares passavam muito tempo jogando. Sim, naquela época não estávamos falando de smartphones, apenas de telefones.
Foi um bom momento, como diz o ditado, e a Nokia popularizou o jogo através dos seus dispositivos móveis, que também foram uma referência. Hoje, não resta muito do domínio da Nokia no mundo móvel e no jogo Snake.
Para quem tem saudades deste jogo – e eu sou um deles, devo admitir – este tutorial vai te ensinar como recriá-lo para a Web. Para fazer isso, usarei a API Canvas do HTML5 e o JavaScript.
É também uma oportunidade de aprender como usar classes em Javascript e criar um loop de jogo eficaz para jogos na Web.
Para começar, criaremos a página Web que nos permitirá jogar o jogo Snake que desenvolveremos neste tutorial. Você logo verá que esta página Web não apresenta nenhuma dificuldade. Duas divs, uma para o título da página e outra para exibir a área por onde a cobra se moverá.
Para isso, adicionarei um pouco de CSS para centralizar essas divs aplicando uma largura fixa a elas:
Como expliquei na introdução deste tutorial, usarei uma classe Snake dedicada para modelar o jogo. Isso também permitirá que você descubra como manipular classes em JavaScript.
Nossa Snake terá as seguintes propriedades:
No final do construtor, um método init é chamado para inicializar a cobra no início do jogo. Quando um novo jogo for iniciado, basta chamar este método init novamente.
Isso nos dá o seguinte código para nossa classe Snake:
No método init, você pode definir outras propriedades da cobra, como um ponteiro para a cabeça e um ponteiro para a cauda. O array de elementos armazenará todos os elementos da cobra em um determinado momento. A propriedade points é utilizada para armazenar pontos do jogo atual, enquanto a propriedade level é utilizada para definir quantos pontos são acumulados para aumentar o fps do jogo. Quanto maior o número de fps, mais rápido a cobra se moverá.
Como a propriedade fps representa o número de quadros por segundo, precisamos ter uma propriedade fpsinterval avaliada como resultado da divisão de 1 segundo (ou 1.000 milissegundos) pelo número desejado de fps.
O princípio do jogo Snake é simples: você deve guiar a cobra usando as quatro setas direcionais para que ela coma o número máximo de maçãs que aparecem no tabuleiro. Cada vez que você come uma maçã, a cobra cresce em um elemento. À medida que a cobra cresce, será difícil evitar tocar na própria cauda. Caso contrário, você perderá e o placar começará novamente do zero. Claro, cada vez que você come uma maçã, você ganha um ponto.
Vale ressaltar que a versão do Snake que vamos implementar é aquela em que tocar nas bordas do tabuleiro não faz perder. Isso apenas faz você tombar para o lado oposto. As segundas versões do jogo Snake foram implementadas desta forma pela Nokia.
Como a cobra tem que comer uma maçã, precisamos exibir essa maçã no tabuleiro de forma aleatória, tomando cuidado para não gerar uma maçã diretamente sobre um elemento da cobra.
Isso nos dá o seguinte método generatefood para nossa classe Snake:
Nossa classe Snake está progredindo e agora precisamos criar um método para renderizar a cobra na tela. Também precisaremos exibir o número de pontos do jogador em um determinado momento e, por fim, exibir a maçã a ser comida. A posição da maçã é armazenada na propriedade food da classe Snake.
Para renderizar o Snake na tela, estou usando a API Canvas do HTML5.
Usarei as primitivas de desenho desta API para desenhar retângulos representando os vários elementos da cobra, bem como a maçã a ser comida. Aplicarei uma cor diferente à maçã e à cobra para que o jogador possa distingui-las.
Isso fornece o seguinte código para o método draw da nossa classe Snake:
Agora temos uma cobra que podemos exibir na tela. Está tudo muito bem, mas precisamos adicionar suporte para o movimento da cobra. Conforme explicado acima, a cobra se move ao longo do vetor de coordenadas (dirx, diry). Então, cada vez que chamarmos o método move que vou definir aqui, a cobra se moverá na mesma proporção.
Neste método de movimento verificamos se as coordenadas da cabeça da cobra correspondem às da maçã a ser comida. Se for assim, a cobra acabou de comer a maçã. O jogador marca um ponto, mas o mais importante é que precisamos realizar quatro ações:
Ainda assim, no método de movimento, precisamos verificar se o jogador não cometeu o erro de tocar com a cabeça em algum elemento da cobra. Se for esse o caso, o jogo está perdido e começamos de novo! Para fazer isso, chamamos o método init da classe Snake apresentado acima.
Agora, precisamos completar o método move movendo a cobra. Para fazer isso, adicionamos dirx e diry às coordenadas da cabeça da cobra. Isso nos dá uma nova cabeça para adicionar. Você também notará que mover a cobra é feito de forma inteligente, removendo a cauda a cada vez e adicionando uma nova cabeça. Isto evita ter que atualizar a posição de todos os elementos da cobra.
Termine lembrando de atualizar o novo cabeçote. Aliás, você também deve ter notado que quando a cabeça da cobra cruza os limites do tabuleiro, fazemos com que ela se mova para o lado oposto do tabuleiro. Isso se aplica tanto à largura quanto ao comprimento.
Isso nos dá o seguinte código para o método move:
Nossa Snake pode ser exibida na tela. Nossa Snake pode ser movida chamando seu método move. O que estamos perdendo?
Estamos sentindo falta da implementação do GameLoop do nosso jogo!
Sem este GameLoop, que chamará os métodos move e draw em intervalos regulares, o Snake não será capaz de se mover. A seguir, mostraremos como implementar um GameLoop da maneira correta em JavaScript, deixando que o navegador o chame quando achar necessário para não bloquear o thread de renderização da página web do jogo.
Para fazer isso, usaremos o método requestAnimationFrame da janela de objeto JavaScript padrão. O navegador irá então adaptar o fps máximo que pode suportar ao computador ou smartphone no qual a página da web será usada.
Dentro do nosso método gameloop, iremos então descorrelacionar o número de fps suportados pelo navegador do número de fps que queremos mover em nossa cobra. Chamaremos os métodos move e draw apenas quando estivermos dentro da faixa de fps definida anteriormente.
É importante atualizar as coordenadas do vetor de movimento da cobra de acordo com o estado das quatro teclas direcionais: para cima, para baixo, para a esquerda e para a direita.
Por fim, chamamos o GameLoop, delegando ao navegador a tarefa de escolher o melhor momento para fazê-lo. Isso nos dá o seguinte código para o GameLoop:
Para permitir que o Snake seja movido de acordo com as teclas direcionais pressionadas pelo jogador, utilizamos os eventos keydown e keyup. Para cada um desses eventos, chamaremos um método da classe Snake. Logicamente, isso será pressionado para o evento keydown e pressionado para o evento keyup.
Atualizamos o valor das propriedades vinculadas da classe Snake de acordo com o que o jogador faz com essas chaves. Como você pode ver, não bloqueamos o jogo atualizando diretamente a posição da cobra. Em vez disso, atualizamos o estado no método gameloop, que é chamado em intervalos regulares.
Para completar este jogo Snake, precisamos montar os vários elementos. Recuperamos o objeto Canvas por meio de seu ID. Então, obtemos o contexto 2D vinculado a este Canvas. Aplique as dimensões desejadas. Criamos um objeto Snake, passando como parâmetros os diversos valores esperados, incluindo o número de células do tabuleiro.
Adicione os ouvintes de eventos para os eventos keydown e keyup.
Finalmente, tudo o que resta fazer é chamar o gameloop do Snake uma vez para iniciar o jogo. Isso nos dá o seguinte código completo para o famoso jogo Snake feito com a API Canvas e o casal infernal HTML5/JavaScript Web:
Nosso Snake está completo, é hora de testá-lo em um navegador da Web para ver se a magia do Snake funciona novamente, como aconteceu quando a Nokia dominou escandalosamente o mundo móvel:
A partir deste jogo Snake, você pode imaginar várias melhorias possíveis. Por exemplo, você pode adicionar um som cada vez que a cobra come a maçã. Você poderia usar a API Web Storage do HTML5 para armazenar a pontuação mais alta local de um jogador. Dessa forma, quando um jogador bater sua pontuação mais alta, você poderá exibir uma mensagem de parabéns. As possibilidades são infinitas e o seu único limite, como sempre na programação, é a sua imaginação.
Este tutorial também pode ser assistido no YouTube no canal SSaurel:
Também publicado aqui .