Fazendo um jogo HTML5 sem engine e sem framework
· 3 min de leitura
Seis dos nove primeiros jogos da nossa página de jogos são lançados sem dependência de nenhum tipo: não usam engine, framework nem biblioteca em tempo de build. O menor, Reefhold, tem 63 KB em disco: o jogo inteiro, arte incluída. Os três mais novos quebram a regra de propósito, e vale explicar o porquê nas duas direções.
O que "sem engine" quer dizer na prática
Na prática, são três coisas: um elemento <canvas>, um loop movido por
requestAnimationFrame, e cada forma na tela desenhada por código em vez de
carregada como imagem. Não há scene graph, nem entity-component system, nem
pipeline de assets. Um sprite é uma função que recebe um contexto e alguns
números e chama fillRect algumas vezes.
Parece primitivo porque é. E também é o motivo de o Reefhold carregar antes de você terminar de ler o título.
As três coisas que você acaba escrevendo sozinho
Um engine te entrega isto de graça. Sem um, estes são os três primeiros arquivos que você escreve, e são os mesmos três arquivos em todo jogo:
- Um loop de timestep fixo. O
requestAnimationFramete dá um delta de tempo real, não um tick. Se você move as coisas usando esse delta diretamente, o jogo roda diferente num notebook de 60 Hz e num monitor de 144 Hz, e uma física que parecia certa nos testes fica estranha no mundo real. A solução é acumular o tempo real e avançar a simulação em fatias fixas, renderizando uma interpolação entre as duas últimas. - Uma entrada que seja igual no toque e no teclado. Metade do tráfego é
celular. Um jogo que lê
keydowne mais nada é injogável para essas pessoas, e um que trata o toque como caso especial em todo lugar tem o dobro de código. O truque é normalizar os dois num pequeno objeto de "intenção" (uma direção e um conjunto de ações pressionadas) e deixar o resto do jogo ler só isso. - Um áudio que sobreviva à política de autoplay. O navegador não deixa um
som tocar até o usuário interagir com a página. Se você cria o seu
AudioContextno carregamento, ele começa suspenso e nunca se recupera. Crie-o no primeiro evento de ponteiro ou de tecla, e condicione todo som posterior a isso.
São umas 150 linhas, compartilhadas sem alteração entre os jogos que as usam.
O que isso compra
- Um pacote que nenhum portal questiona. Os portais curados têm limites de tamanho rígidos e rejeitam o que passa deles, sem recurso. Um jogo de 63 KB nem entra em discussão.
- Um primeiro carregamento instantâneo, o que no 4G é a diferença entre um jogador e alguém que vai embora.
- Nada para licenciar. Quando alguém pede para licenciar um desses jogos, não há licença de terceiros para mostrar, nem arquivo de atribuição, nem "bom, depende do Phaser, e o Phaser é MIT, mas".
Onde fica o limite
Scrapforge, ScaleSling e Husktide são feitos em Phaser, e essa foi a decisão certa para os três. Scrapforge e ScaleSling precisam de um solver de física de verdade, e um solver de restrições 2D não é algo que valha a pena escrever de novo, e mal. Husktide põe centenas de entidades na tela ao mesmo tempo e depende de um atlas de texturas e de um renderizador ajustado para isso.
Olhando para trás, o padrão é bem claro: a abordagem pura escala para jogos sobre posicionamento e timing (a maioria dos puzzles, a maioria dos idle, a maioria dos arcades de pontuação). Ela para de escalar no momento em que você precisa de muitos corpos interagindo ou de um modelo de física cheio de casos difíceis. A partir daí, um engine não é sobrecarga: é o que mantém o pacote menor do que a versão feita à mão acabaria ficando.
Os tamanhos de cada jogo estão todos publicados na página de licenciamento, se você quiser os números exatos.
