Desenvolvendo um jogo em React sem instalar nada

Fabio Oliveira
pergunteaodev
Published in
6 min readJan 3, 2018

No dia 8 de dezembro eu apresentei em um meetup do FreeCodeCamp-São Paulo como desenvolver um jogo em React. O tempo não deu muito certo, mas para a primeira vez considero que foi ótimo.

Edição do jogo

O jogo que criei está aqui e pode ser editado aqui, ele é um clone bastante simples do flappy bird e certamente vou iterar algumas vezes sobre o projeto.

Como não instalar nada

Qualquer pessoa que tenha começado com React sabe que a parte mais difícil é a instalação. É necessário ter o Node instalado, configurar o WebPack , baixar as dependências e etc, embora tudo seja mais fácil atualmente com o create-react-app ainda assim não era fácil o suficiente.

Felizmente o stackblitz chegou até mim através de um podcast ele é basicamente um editor de código e servidor de uma app React no navegador. Isso facilita imensamente já que o pública era bem diverso com diversos sistemas operacionais .Algumas pessoas podem nunca ter tocado num editor de código ou linha de comando.

O que um jogo nos ensina

Um jogo é algo extremamente interessante para estudar desenvolvimento:

  • Se algo está errado é visualmente claro;
  • É essencialmente divertido;
  • É fácil de entender;
  • Há um conceito de mudança com o tempo que nos obriga a pensar em estado e etc;

Um jogo também possui regras claras (diferente de certos problemas que, descobrir as regras é grande parte do processo), nesse jogo específico nós temos as seguintes:

  • O jogador está caindo constantemente;
  • Há obstáculos vindo em direção ao jogador;
  • Se o jogador tocar um dos obstáculos ele perde;
  • Se o jogador tocar o topo ou o começo da tela ele perde;

Pensando em React

No site do React é dito que ele é declarativo e baseado em componentes. Então nos convém pensar em nosso jogo nesses termos.

Declarativo — É um paradigma (regra, forma de pensar) de programação em oposição ao imperativo. Ao invés de dizer como as coisas são feitas é dito como elas devem ser, por exemplo:

Nessa analogia vamos supor que há 2 padeiros. O Sr Declarativo e o Sr Imperativo, ambos querem que você faça um bolo.

O Sr Declarativo diz o seguinte:

“Ovos e farinha compõe a massa, chocolate derretido é a cobertura.A massa e a cobertura é o bolo”

O Sr Imperativo diz o seguinte:

“Pegue 3 ovos, quebre eles, misture com a farinha bata utilizando um whisker, separe essa massa em uma forma e coloque a forma no forno médio por 30 minutos. Derreta o chocolate no fogo alto mexendo frequentemente para não grudar. Retire o bolo do forno, retire-o da forma, despeje a cobertura em cima do bolo”

Essa é a diferença, o modo imperativo te diz COMO fazer e o declarativo só DECLARA como as coisas são. Para o desenvolvedor normalmente é muito mais confortável apenas dizer como as coisas são e deixar algo mais complexo cuidar de “como fazer o bolo”.

Baseado em componentes — A ideia aqui é que tudo que compõe algo logicamente é separado em partes. No nosso exemplo do bolo acima, apesar da massa ser composta de ovo e farinha no que toca o objetivo final só Massa e Cobertura todas contidas que nos interessa.

Essa é a mentalidade que temos que ter quando lidamos com React, não nos apegar em dizer como as coisas mudaram de um estado para outro e colocar tudo de relevante em um componente.

Quebrando o jogo em partes

O jogo em si é composto apenas pelas linhas abaixo:

Render do jogo

No código acima nos podemos ver os nossos componentes BgMusic, Background, Hud, Player e Obstacle e como nós apenas declaramos o jogo.

Nessas poucas linhas de código é possível observar a parte mutável do nosso jogo:

  • A música de fundo (BgMusic) possui estados dizendo se elas está mutada, o jogo está rodando ou se está no GameOver;
  • O fundo (Background) também se interessa se está num fim de jogo ou se o jogo está rodando;
  • A tela (Hud) se preocupa com os pontos , se está mutado e possui uma função para mutar ou desmutar;
  • O jogador (Player) se importa se o jogo está rodando, se é fim de jogo e com a posição;
  • Há uma lista de obstáculos (Obstacle) com largura e posição;

O componente da música:

A nossa música é o seguinte código:

Simplesmente se está mudado não envie nada, se for gameOver a música de gameOver, se estiver rodando a música do jogo e senão a música de espera.

Perceba que não é dito como mudar de uma música para outra , nós simplesmente analisamos como as coisas são atualmente e dizemos como elas devem ser baseadas nisso. O paradigma declarativo em ação.

O componente do fundo e o começo do CSS no JS

O nosso fundo é o código abaixo e diversas coisas interessantes estão acontecendo nele.

Logo no início nós percebemos algo diferente nesse código, tem CSS nele. Embora tenha pessoas que não gostem de misturar eu acredito que uma vez que o React valoriza a componetização colocar tudo que nosso fundo precisa em um só lugar é algo desejável. O CSS no JS neste aplicativo é feito pela biblioteca styled-components.

No CSS nós temos algumas coisas interessantes:

Na parte do componente em si, nós também temos uma novidade, começamos a brincar com estado e com métodos do ciclo de vida do react.

Nós não queremos mostrar o gameOver abruptamente então nós esperamos 2 segundos para mostrar a tela (linha 46).

O jogador e animações

O jogador está abaixo e assim como no fundo nós temos o “CSS no JS”

Aqui de interessante há o uso de animações, criamos uma para quando o jogo está funcionando e uma para o gameover.

A escolha dessas animações está no próprio styled-components, fazendo com que essa classe seja bastante simples.

Como o jogo realmente funciona

O cerne do jogo foi colocado no index.js e basicamente ele funciona da seguinte forma:

  • Ouça os botões e faça ações de acordo com elas;
  • A cada segundo do jogo rodando crie novos obstáculos e faça o jogador cair;
  • Confira se o jogador colidiu com algo;

Ouvindo os botões

Através de um listener nos conferimos os seguintes botões

Se o jogo não está rodando e o botão é enter o jogo inicia, se o jogo está rodando nós atualizamos os controles apropriados.

Perceba aqui que nós estamos mudando uma variável e não mexendo com o estado. Porque isso? Bem nós não queriamos forçar o jogo a redesenhar a cada botão ao invés disso optamos por ouvir os botões e a cada novo intervalo agir da forma apropriada.

Checando colisões

A checagem de colisões é feita de forma bastante rústica, para cada um dos nossos obstáculos nos checamos se o jogador está numa altura “colidível” e se sim se o movimento do jogador estiver na largura ele colidiu.

A cada intervalo

Toda a lógica real do jogo está sendo implementada na parte do intervalo como:

  • Resposta aos controles;
  • Criação de novos obstáculos;
  • Checagem de colisão;
  • Atualização da pontuação.

Isso está no código abaixo, que baseado no estado anterior atualiza o novo estado e faz todo o jogo funcionar:

Considerações finais.

Isso foi uma visão geral do projeto e um exemplo funcional de um jogo em React. A imagem do jogador (o pato) não foi criada por mim e sim está no fantástico projeto openClipart, a música também não foi criada por mim e sim foi disponibilizada gratuitamente por Tanner Helland.

Eu devo revisitar esse exemplo no futuro e dar a mesma palestra (com mudanças e melhor preparação) algumas vezes. Se você tem algum feedback por favor me mande por aqui, no facebook ou até mesmo no pergunteaodev.com.

--

--