Guia

Como colocar um jogo HTML5 no meu site: enviar, incorporar e corrigir

Passo a passo para uma pasta de jogo estática: onde ela vai, como abrir, como colocar numa página e o que conferir quando o jogo não abre.

Polarzinho empurra uma caixa de jogo por um tubo brilhante, de um servidor até uma janela de navegador que mostra um jogo de ilhas flutuantes.

Como colocar um jogo HTML5 no meu site? Envie o conteúdo da pasta game/ para qualquer hospedagem que sirva arquivos estáticos, mantenha as subpastas exatamente como vieram e abra o endereço da pasta no navegador. A pasta game/ pronta para hospedar, em qualquer edição do nosso marketplace, roda como está: sem PHP, banco de dados, build nem conta. A hospedagem só entrega arquivos ao navegador do jogador.

Esse é o trabalho inteiro quando tudo dá certo. Este guia é sobre os outros dias: tela em branco, erro 404, aviso de tipo MIME, um iframe que não mostra nada. Nós vendemos esses templates, então leia como um manual de campo dos nossos próprios pacotes. Servimos cópias do Gridspark e do Velvet Pool num servidor local descartável, quebramos o Gridspark de propósito de várias maneiras e lemos os manuais públicos de outras edições. Quando uma informação vem de um manual e não do nosso teste, avisamos.

O que hospedar um jogo HTML5 envolve de verdade

Uma hospedagem estática guarda arquivos e entrega ao navegador quando ele pede. Ela nunca executa o jogo: quem executa é o navegador do jogador. Por isso os requisitos das nossas edições são tão simples: um navegador atual, uma hospedagem que sirva arquivos estáticos por HTTP ou HTTPS e nenhum PHP, banco de dados ou conta para jogar. A pasta game/ já vem compilada, então publicá-la não exige npm nem build.

Dois limites que vale conhecer antes de começar. Algumas edições têm partes opcionais que não são estáticas: Zabum e Ricopop listam um ranking opcional que pede PHP 7.4 ou mais novo e uma pasta com permissão de escrita, e as edições em TypeScript (Beep Out, Pinloop, Trimora, Twirldrop, Riffvolt, Sunset Rally, Tenguin, Mochi Monsters, Deepforge, Barricade Z e Zabum) só precisam de Node.js se você quiser editar o código-fonte e recompilar; cada manual informa a versão. Velvet Pool, Puttide, Ricopop e Gridspark vêm em JavaScript puro, sem etapa de compilação entre as suas edições e os arquivos que você envia. Nada disso é necessário para publicar o jogo como ele é entregue. E a hospedagem em si não faz parte da compra. Os termos da loja listam hospedagem e instalação no seu servidor entre os serviços à parte, orçados antes de qualquer trabalho. O suporte cobre dúvidas sobre instalar e usar os arquivos entregues.

O que sobe e o que fica no seu computador:

  • Envie tudo o que está dentro de game/: index.html, scripts, estilos, imagens, sons e fontes.
  • Deixe de fora source/ (a cópia editável para desenvolvedores), documentation/ (o manual) e o próprio ZIP. O manual do Zabum cita o envio de source/ por engano como causa de erros 404, como o do main.tsx.
  • Guarde junto do seu produto os avisos de licença de terceiros que acompanham o pacote, como pedem os termos.

Ver o Gridspark, a edição que usamos de exemplo

Como colocar um jogo HTML5 no meu site: o caminho curto do ZIP à página jogável

Os passos abaixo seguem os capítulos de instalação dos manuais do Velvet Pool, Puttide, Gridspark e Sunset Rally, mais as conferências que acrescentamos depois dos testes. O exemplo é o Gridspark, a edição que mais servimos e quebramos.

  1. Descompacte o pacote no seu computador. Dentro estão game/ (a pasta que você publica), source/ (a cópia editável) e documentation/ (o manual).
  2. Opcional, mas barato: teste localmente. Abra um terminal dentro de game/, rode python -m http.server 8765 e acesse http://localhost:8765/. Se joga ali, os arquivos estão bons e qualquer problema depois é da hospedagem.
  3. Escolha agora o endereço final, por exemplo https://seu-site.com.br/jogos/gridspark/. Uma subpasta funciona porque os caminhos dentro do jogo são relativos; o manual do Gridspark sugere public_html/games/gridspark/.
  4. Envie o conteúdo de game/ para essa pasta pelo gerenciador de arquivos da hospedagem ou por um cliente FTP, mantendo todas as subpastas. O index.html tem que ficar direto dentro da pasta, não um nível abaixo.
  5. Abra o endereço da pasta por https, com a barra no final. No Gridspark você toca na tela inicial (o navegador espera um toque ou clique antes de liberar o áudio) e aperta Play.
  6. Faça uma jogada, recarregue a página e confira se o menu agora oferece Continue. Isso prova que o navegador está guardando o progresso para o seu endereço.
  7. Coloque um link para a pasta no seu site, ou incorpore o jogo numa página (veja a seção do iframe, mais abaixo).

Uma pasta pronta do Gridspark tem index.html, style.css, gridspark.config.js, src/ e assets/ lado a lado, e o manual pede para mantê-los juntos. Outras edições organizam diferente (o Velvet Pool tem css/ e assets/ em vez de um único arquivo de estilo), mas a regra é a mesma: envie a pasta como ela vem.

Por que dar dois cliques no index.html deixa a página em branco

As edições que abrimos carregam o código como módulos ES, e o navegador se recusa a carregar módulos de endereços file://. Abrimos o Gridspark direto do disco no Chromium e veio uma tela escura e vazia. O console avisou que o script foi bloqueado pela política de CORS, com o motivo "Cross origin requests are only supported for protocol schemes" (só há suporte a http, https e alguns outros esquemas). A mesma pasta servida por um servidor local mostrou a tela inicial na hora. Os manuais do Velvet Pool, Puttide, Sunset Rally e Gridspark dizem o mesmo: não abra o jogo por file://.

  • Não funciona: file:///C:/Users/voce/jogos/gridspark/index.html
  • Funciona: http://localhost:8765/ num servidor de teste local, ou https://seu-site.com.br/jogos/gridspark/ na sua hospedagem.

Testamos só no Chromium. Os manuais tratam o bloqueio como algo comum nos navegadores, então conte com ele em todos.

Incorporar o jogo numa página com iframe

Para mostrar o jogo dentro de uma página que você já tem, aponte um iframe para a pasta enviada. Esta é a tag que testamos:

<iframe src="https://seu-site.com.br/jogos/gridspark/" title="Gridspark" allow="fullscreen; autoplay" width="960" height="540" style="border:0"></iframe>

  • src: o endereço completo da pasta, com https e a barra no final.
  • title: um nome curto. Leitores de tela usam o título para descrever o quadro.
  • allow="fullscreen; autoplay": os manuais mandam liberar tela cheia e autoplay no iframe quando preciso. No nosso teste, um quadro de outro endereço sem isso ficou com a tela cheia desativada, e o Gridspark simplesmente escondeu o botão de tela cheia. O atributo antigo allowfullscreen deu o mesmo resultado que o allow. Um quadro no mesmo endereço da página tem tela cheia de qualquer jeito.
  • Sem o atributo sandbox. Só com sandbox="allow-scripts", o Gridspark nem começou: o quadro ganha uma origem nula, o navegador bloqueou o script do próprio jogo e o armazenamento local lançou um erro de segurança. Com allow-same-origin funciona, mas a MDN avisa que esse par num quadro de mesma origem tira a proteção. Num jogo hospedado por você, deixe o sandbox de fora.

Dimensione para o celular

Uma caixa fixa 16:9 fica certa no computador e errada no celular. Com 390 px de largura, um iframe com aspect-ratio 16/9 tem só 219 px de altura, e o menu do Gridspark foi cortado logo abaixo do botão Daily challenge. Dar ao quadro a altura de 75svh, três quartos da altura da tela, mostrou o menu inteiro. A sua página também precisa da meta tag viewport; os seis pacotes que abrimos trazem uma no próprio index.html, e é por isso que o jogo se ajusta quando aberto direto.

Duas telas de celular lado a lado, cada uma com uma página que mostra o menu inicial do Gridspark dentro de um iframe: à esquerda um quadro baixo 16:9 que corta o menu, à direita um quadro alto que mostra o menu inteiro.
O mesmo jogo, na mesma largura de celular. Esquerda: iframe 16:9. Direita: quadro com 75svh de altura.

O jogo funciona no próprio endereço, sem página em volta, então um link simples para esse endereço é sempre uma alternativa válida.

Ver o Velvet Pool, uma edição 3D que se incorpora do mesmo jeito

WordPress e outros construtores de site

Hospedar a pasta e mostrá-la numa página são dois trabalhos separados, e no WordPress cada um usa uma ferramenta. Tudo abaixo vem da documentação e da referência para desenvolvedores do WordPress, não de uso próprio do WordPress.

  1. Envie a pasta pelo gerenciador de arquivos da hospedagem ou por FTP, para dentro da árvore de pastas do site (por exemplo uma pasta jogos/ ao lado das pastas do WordPress). Não pela Biblioteca de mídia: o código do WordPress tira .html e .js dos tipos de upload permitidos, a menos que o usuário tenha a capacidade unfiltered_html.
  2. Abra o endereço da pasta sozinho antes de mexer em qualquer página. As regras padrão do Apache que o WordPress documenta só mandam a requisição para o index.php quando não existe arquivo nem pasta correspondente (é isso que as condições !-f e !-d testam), então uma pasta enviada é servida como está.
  3. Coloque o iframe num bloco HTML personalizado. A documentação do WordPress informa que usuários sem a capacidade unfiltered_html, um Colaborador por exemplo, têm as tags iframe removidas quando o post é salvo. Se o quadro sumir depois de salvar, confira quem editou a página.

Outros construtores de site e CMSs: não testamos e não afirmamos nada sobre nenhum deles. O jogo precisa das mesmas duas coisas em qualquer lugar, um lugar para a pasta enviada e um elemento de incorporação que aceite iframe. Se o construtor não oferece nenhum dos dois, hospede a pasta onde houver arquivos estáticos e coloque um link para o endereço.

Quando não abre: uma lista de problemas e soluções

Abra as ferramentas de desenvolvedor do navegador (F12 na maioria dos navegadores de computador) e olhe as abas Console e Rede (Network) antes de mudar qualquer coisa. Cada falha abaixo deixa uma linha vermelha ali, e o nome do arquivo nela costuma apontar a causa.

Tela em branco

Confira nesta ordem: o endereço começa com http:// ou https://; o Console não tem linhas vermelhas; os nomes de arquivo mantêm exatamente as maiúsculas e minúsculas; e, nas edições 3D, o WebGL2 está disponível (o manual do Velvet Pool manda ativar a aceleração por hardware). Hospedagens Linux tratam Game.js e game.js como dois arquivos, e o Windows não, então uma pasta que funcionava no seu PC pode quebrar depois do envio. Os manuais do Velvet Pool e do Zabum avisam disso.

404 em src/main.js, fontes ou imagens

Uma parte da pasta não chegou, ou chegou um nível abaixo do certo. Reproduzimos enviando só index.html, style.css e o arquivo de configuração: a tela ficou em branco e a aba Rede listou 404 para src/main.js e para todas as fontes. Envie as pastas que faltam, ou suba o conteúdo para que o index.html fique no endereço que você abre. Se imagens ou sons faltam ou vieram corrompidos, o manual do Zabum sugere FTP em modo binário ou automático, ou enviar um ZIP e extrair no gerenciador de arquivos da hospedagem. Um 404 é arquivo faltando. Não é problema de MIME.

A página abre sem estilo, com ícones gigantes

Se uma regra de reescrita ou de URL limpa serve a pasta sem a barra final, os caminhos relativos passam a valer um nível acima. Reproduzimos com um servidor de teste que devolve a página da pasta sem redirecionar. O navegador pediu /games/style.css e /games/src/main.js em vez dos arquivos de /games/gridspark/, recebeu 404 e desenhou o menu como botões crus e ícones enormes. Faça o link da pasta com a barra no final, ou aponte direto para o index.html.

Uma janela de navegador com página branca, botões cinza sem estilo e ícones pretos enormes: o menu do Gridspark sem a folha de estilo.
O Gridspark aberto num endereço sem a barra final, num servidor que não redireciona: sem folha de estilo e sem script.

Erro de tipo MIME num script de módulo

No nosso teste o console mostrou: Failed to load module script: Expected a JavaScript-or-Wasm module script but the server responded with a MIME type of "text/plain". O navegador é rígido com scripts de módulo. Os manuais dizem que o servidor precisa enviar os arquivos .js com um tipo MIME de JavaScript, e .wasm como application/wasm; o manual do Sunset Rally acrescenta .mjs. A aba Rede mostra o Content-Type de cada arquivo. Nas versões que abrimos, os módulos são arquivos .js. Se você acrescentar arquivos .mjs seus e uma configuração antiga do Apache não os reconhecer, uma linha no .htaccess resolve, a mesma que o nosso próprio site usa:

AddType text/javascript .mjs

A tabela de tipos do Apache 2.4.62 da nossa máquina de teste já associa js e mjs a text/javascript e wasm a application/wasm, então uma instalação padrão não precisa da linha. Outros servidores têm suas próprias tabelas; pergunte a quem cuida do seu.

Blocked by CORS policy

Scripts de módulo e fontes carregados de outro endereço precisam de um cabeçalho Access-Control-Allow-Origin vindo desse endereço. No nosso teste, uma página numa porta não conseguiu carregar um script de módulo de outra porta até o segundo servidor enviar o cabeçalho. Na prática a solução é sem graça: mantenha os arquivos do jogo juntos numa pasta, num endereço só, que é como os pacotes são montados. Você não precisa de CORS para incorporar o jogo num iframe em outro site, porque o iframe só carrega o endereço do jogo. Um erro de CORS dentro de uma incorporação costuma vir do atributo sandbox, descrito acima.

Conteúdo misto numa página https

Uma página servida por https não pode carregar scripts nem iframes por http: os navegadores bloqueiam os dois, e a MDN lista fontes e requisições fetch entre os tipos bloqueados. Use https:// no src do iframe e em qualquer endereço completo que você digitou. Os arquivos do próprio jogo usam caminhos relativos, então seguem o protocolo do endereço que você abriu. Se o endereço https nem abre, ative o certificado no painel da hospedagem primeiro.

O iframe diz "refused to connect"

No nosso teste o Chromium registrou esta linha, com o endereço do quadro bloqueado nas primeiras aspas: Refused to display 'https://game-host.example/' in a frame because it set 'X-Frame-Options' to 'sameorigin'. O servidor que hospeda o jogo estava enviando esse cabeçalho. SAMEORIGIN só permite incorporar a partir do mesmo endereço, e DENY nunca permite; uma regra frame-ancestors num cabeçalho Content-Security-Policy faz um papel parecido. Mude o cabeçalho da pasta do jogo, ou sirva a página e o jogo pelo mesmo endereço.

Sem áudio no começo

Os navegadores bloqueiam o áudio até o primeiro toque ou clique, e é por isso que o Gridspark abre numa tela de toque para começar. Toque uma vez e depois confira o volume e as permissões do navegador.

Ver o Puttide, a edição de golfe com build pronto para hospedar

Atualizar o jogo sem servir uma versão pela metade

Os navegadores guardam scripts em cache, então depois de um envio você ou um jogador ainda podem estar vendo o jogo antigo. O manual do Gridspark dá a regra: faça backup das suas edições, troque os arquivos jogáveis como um conjunto, teste e force a atualização se a hospedagem guardar módulos antigos. Não misture módulos antigos e novos. Um jogo feito de muitos arquivos pequenos que importam uns aos outros é a pior coisa para atualizar pela metade.

Edições com service worker mantêm um cache próprio. O Zabum é um PWA: depois de uma atualização, force a recarga (Ctrl ou Cmd mais Shift mais R). Se você trocou arquivos de áudio, mude o nome do cache em sw.js (o exemplo do manual vai de zabum-v5 para zabum-v6) e envie esse arquivo. Se o seu site fica atrás de uma CDN, limpe o cache dela também. Entre os manuais que lemos, o Zabum é o único PWA; os manuais do Velvet Pool e do Puttide dizem claramente que as edições deles não são um app offline instalável.

Leia o changelog antes de trocar os arquivos e guarde uma cópia de tudo o que você editou. O progresso fica no navegador de cada jogador, não na pasta que você envia, então trocar os arquivos não apaga o progresso.

Ver o Zabum, a edição PWA com ranking opcional em PHP

Onde o progresso fica salvo e o que acontece quando o jogador limpa o navegador

Essas edições não têm contas nem banco de dados no servidor. Ajustes, idioma, a partida em andamento e os recordes pessoais ficam no armazenamento local do navegador, e nada é enviado para a Polar Games. O manual do Gridspark cita as chaves gridspark.standalone.v1.*; depois de uma jogada vimos gridspark.standalone.v1.best e gridspark.standalone.v1.save.

O menu principal do Gridspark com o botão Continue, o link New game, o botão Daily challenge e um recorde salvo de 3.257 pontos.
Numa nova visita, o menu oferece Continue e o recorde salvo. Os dois são lidos do navegador.

O armazenamento pertence ao endereço (protocolo, host e porta), não à pasta. Conferimos de três jeitos. Uma cópia do Gridspark em outra pasta do mesmo endereço leu os mesmos valores salvos. O mesmo jogo aberto como localhost em vez de 127.0.0.1 começou vazio, e o mesmo endereço em outra porta também. O manual do Zabum acrescenta que http e https, www e sem www, e subdomínios têm cada um o seu armazenamento.

  • Limpar os dados do site ou os cookies apaga a partida salva e os recordes. Numa janela privada o progresso pode durar só a sessão; o jogo continua rodando quando o armazenamento está bloqueado.
  • Outro navegador ou outro aparelho começa do zero. Não há sincronização nem conta para entrar.
  • Mudar o endereço zera todo mundo: de http para https, de www para sem www, um domínio novo.
  • Mover o jogo para outra pasta do mesmo endereço mantém o progresso, como mostrou o nosso teste com o Gridspark.

Uma lista de testes antes de divulgar o link

  1. Abra o endereço final nos navegadores que seus jogadores usam: um baseado em Chromium (Chrome ou Edge), o Firefox e o Safari. Nossos testes rodaram só no Chromium, então esta é a lista para você executar.
  2. Abra num celular de verdade, primeiro no endereço próprio do jogo e depois dentro da sua página, nas duas orientações.
  3. Limite a velocidade da conexão nas ferramentas de desenvolvedor e acompanhe o primeiro carregamento. O Gridspark, servido sem compressão pelo nosso servidor local, precisou de cerca de 0,5 MB e 26 requisições para chegar à tela inicial. Com o Chromium limitado a 1,6 Mbit/s e 150 ms de latência, a tela apareceu em cerca de 3 segundos. A pasta game/ inteira tem cerca de 3,4 MB na nossa cópia; o Velvet Pool tem cerca de 7,3 MB e o Puttide cerca de 15 MB. Se celulares antigos sofrerem, o manual do Zabum sugere conferir se a hospedagem comprime os arquivos com gzip ou brotli.
  4. Faça uma jogada, recarregue e confirme que o Continue e o recorde estão lá.
  5. Toque uma vez e confira se o áudio começa. Silêncio antes do primeiro toque é normal.
  6. Abra uma janela privada. O jogo deve rodar, mesmo que esqueça o progresso quando você fechar.
  7. Leia as abas Console e Rede num primeiro carregamento: nenhuma linha vermelha, nenhum 404.
  8. Numa incorporação, confira se o botão de tela cheia aparece e se o quadro tem altura suficiente no celular.

Perguntas frequentes sobre como colocar um jogo HTML5 no site

Preciso de PHP, banco de dados ou um servidor especial para hospedar um jogo HTML5?

Não nas nossas edições como são entregues. Elas são estáticas: envie a pasta game/ para uma hospedagem que sirva arquivos por HTTP ou HTTPS e abra o endereço. Zabum e Ricopop têm um ranking opcional que pede PHP 7.4 ou mais novo e uma pasta com permissão de escrita.

Posso só dar dois cliques no index.html?

Não. O navegador bloqueia módulos de jogo em file://, e a página fica em branco. Abra o jogo por um endereço http ou https, seja o da hospedagem ou o de um servidor local de teste, como python -m http.server 8765.

Preciso de HTTPS?

Os manuais mandam usar HTTPS na hospedagem pública. O manual do Zabum diz que Adicionar à tela inicial exige HTTPS, e uma página https não consegue incorporar um iframe http, porque o navegador bloqueia como conteúdo misto.

Como coloco o jogo numa página do WordPress?

Envie a pasta pelo gerenciador de arquivos da hospedagem ou por FTP, abra o endereço dela para confirmar que o jogo roda e depois coloque o iframe num bloco HTML personalizado. Usuários sem a capacidade unfiltered_html têm os iframes removidos, então confira o papel de quem edita a página.

Onde o progresso fica salvo e o que acontece se o jogador limpar os dados do navegador?

No armazenamento local do navegador, por endereço. Limpar os dados do site apaga o progresso, outro navegador ou aparelho começa vazio, e trocar o domínio ou alternar entre http e https zera tudo. Não há contas e nada é enviado para nós.

A Polar Games hospeda o jogo para mim?

Não. A loja vende os arquivos. O suporte cobre dúvidas sobre instalar e usar esses arquivos; hospedagem e instalação no seu servidor são serviços à parte, orçados antes de qualquer trabalho.

Próximo passo

Se você ainda não escolheu um jogo, cada página de item lista os requisitos, tem o link do manual e deixa jogar a demo antes de pagar. Leia primeiro o capítulo de instalação do manual: é a página que você vai usar no trabalho deste guia.

Ver os templates de jogos HTML5