Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Personalizar página HTML para exportação Web

Embora os modelos de exportação para a Web forneçam uma página HTML padrão totalmente capaz de iniciar o projeto sem qualquer personalização adicional, pode ser vantajoso criar uma página HTML personalizada. Embora o jogo em si ainda não possa ser controlado diretamente pelo lado de fora com facilidade, essa página permite personalizar o processo de inicialização do motor.

Alguns casos de uso em que a personalização da página padrão é útil incluem:

  • Carregar arquivos de um diretório diferente do da página;

  • Carregar um arquivo .zip em vez de um arquivo .pck como o pacote principal;

  • Carregar o motor de um diretório diferente do arquivo do pacote principal;

  • Adicionar um botão de clique para jogar para que os jogos possam ser iniciados no modo de tela cheia;

  • Carregar alguns arquivos extras antes que o motor inicie, tornando-os disponíveis no sistema de arquivos do projeto o mais rápido possível;

  • Passar argumentos de linha de comando personalizados, por exemplo, -s para iniciar um script MainLoop.

A página HTML padrão está disponível no repositório do Godot Engine em /misc/dist/html/full-size.html, mas o seguinte modelo pode ser usado como um exemplo muito mais simples:

<!DOCTYPE html>
<html>
    <head>
        <title>My Template</title>
        <meta charset="UTF-8">
    </head>
    <body>
        <canvas id="canvas"></canvas>
        <script src="$GODOT_URL"></script>
        <script>
            var engine = new Engine($GODOT_CONFIG);
            engine.startGame();
        </script>
    </body>
</html>

Configurar

Como mostrado pelo exemplo acima, é principalmente um documento HTML normal, com poucos espaços reservados que precisam ser substituídos durante a exportação, um elemento HTML <canvas> e algum código JavaScript simples que chama a classe Engine().

Os únicos placeholders necessários são:

  • $GODOT_URL: O nome do arquivo JavaScript principal, que fornece a classe Engine() necessária para iniciar o motor e que deve ser incluído no HTML como um <script>. O nome é gerado a partir do Caminho de Exportação durante o processo de exportação.

  • $GODOT_CONFIG: Um objeto JavaScript que contém as opções de exportação e que pode ser substituído posteriormente. Veja EngineConfig para a lista completa de substituições.

Os seguintes marcadores de posição opcionais ativarão alguns recursos extras no seu modelo HTML personalizado.

  • $GODOT_PROJECT_NAME: O nome do projeto conforme definido na configuração Name em Configurações do Projeto > Application > Config. É uma boa ideia usá-lo como um <title> no seu modelo.

  • $GODOT_HEAD_INCLUDE: Uma string personalizada para incluir no documento HTML logo antes do fechamento da tag <head>. Ela é personalizada nas opções de exportação na seção Html / Head Include. Embora você controle totalmente a página HTML que criar, essa variável pode ser útil para configurar partes do elemento head do HTML a partir do Editor Godot, por exemplo, para diferentes predefinições de exportação Web.

  • $GODOT_SPLASH: O caminho para a imagem usada como tela de inicialização, conforme definido na configuração Image em Configurações do Projeto > Application > Boot Splash.

  • $GODOT_SPLASH_COLOR A cor de fundo da tela de inicialização conforme definida na configuração BG Color em Configurações do Projeto > Application > Boot Splash, convertida para um código de cor hexadecimal.

  • $GODOT_SPLASH_CLASSES: Este marcador de posição fornece uma string com os nomes das configurações e seus valores que afetam a tela de inicialização. Essa string deve ser usada como um conjunto de nomes de classes CSS, o que permite estilizar a imagem de inicialização com base nas configurações de inicialização do projeto. As seguintes configurações de Configurações do Projeto > Application > Boot Splash são fornecidas, representadas pelos nomes de classes mostrados abaixo, dependendo do valor booleano da configuração:

    • Show Image: show-image--true, show-image--false

    • Stretch Mode: fullsize--true (se não estiver Desativado), fullsize--false

    • Use Filter: use-filter--true, use-filter--false

Quando a página personalizada estiver pronta, ela poderá ser selecionada nas opções de exportação na seção Html / Custom Html Shell.

../../../_images/html5_export_options.png

Iniciando o projeto

Para poder iniciar o jogo, você precisa escrever um script que inicialize o motor — o código de controle. Esse processo consiste em três etapas, mas, como mostrado aqui, a maioria delas pode ser pulada dependendo de quanta personalização é necessária.

Veja a referência de classe do HTML5 shell para a lista completa de métodos e opções disponíveis.

Primeiro, o motor deve ser carregado, depois precisa ser inicializado e, após isso, o projeto pode finalmente ser iniciado. Você pode executar cada uma dessas etapas manualmente e com grande controle. No entanto, no caso mais simples, tudo o que você precisa fazer é criar uma instância da classe Engine() com a configuração exportada e, em seguida, chamar o método engine.startGame, substituindo opcionalmente quaisquer parâmetros de EngineConfig.

const engine = new Engine($GODOT_CONFIG);
engine.startGame({
    // Optional override configuration, for example:
    // unloadAfterInit: false,
    // canvasResizePolicy: 0,
    // ...
});

Este trecho de código carrega e inicializa automaticamente o mecanismo antes de iniciar o jogo. Ele usa a configuração fornecida para carregar o mecanismo. O método engine.startGame é assíncrono e retorna uma Promise. Isso permite que seu código de controle rastreie se o jogo foi carregado corretamente sem bloquear a execução ou depender de polling.

Caso seu projeto precise de um controle especial sobre os argumentos de inicialização e arquivos de dependência, o método engine.start pode ser usado em seu lugar. Observe que este método não pré-carrega automaticamente o arquivo pck, portanto você provavelmente desejará pré-carregá-lo manualmente (e qualquer outro arquivo extra) por meio do método engine.preloadFile.

Opcionalmente, você também pode chamar manualmente o engine.init para realizar ações específicas após a inicialização do módulo, mas antes do início do motor.

Este processo é um pouco mais complexo, mas oferece controle total sobre o processo de inicialização do motor.

const myWasm = 'mygame.wasm';
const myPck = 'mygame.pck';
const engine = new Engine();
Promise.all([
    // Load and init the engine
    engine.init(myWasm),
    // And the pck concurrently
    engine.preloadFile(myPck),
]).then(() => {
    // Now start the engine.
    return engine.start({ args: ['--main-pack', myPck] });
}).then(() => {
    console.log('Engine has started!');
});

Para carregar o motor manualmente, o método estático Engine.load() deve ser chamado. Como este método é estático, múltiplas instâncias do motor podem ser geradas se compartilharem o mesmo wasm.

Nota

Múltiplas instâncias não podem ser geradas por padrão, pois o motor é descarregado imediatamente após ser inicializado. Para evitar que isso aconteça, consulte a opção de substituição unloadAfterInit. Ainda é possível descarregar o motor manualmente depois, chamando o método estático Engine.unload(). Descarregar o motor libera a memória do navegador ao descarregar arquivos que não são mais necessários após a instância ser inicializada.

Personalizando o comportamento

No ambiente Web, vários métodos podem ser usados para garantir que o jogo funcione conforme o esperado.

Se você visa uma versão específica do WebGL ou apenas deseja verificar se o WebGL está disponível, pode chamar o método Engine.isWebGLAvailable(). Ele opcionalmente aceita um argumento que permite testar uma versão principal específica do WebGL.

Como o arquivo executável real não existe no ambiente Web, o motor apenas armazena um nome de arquivo virtual formado a partir do nome base dos arquivos carregados do motor. Esse valor afeta a saída do método OS.get_executable_path() e define o nome do pacote principal iniciado automaticamente. A opção de substituição executable pode ser usada para substituir esse valor.

Personalizando a apresentação

Várias opções de configuração podem ser usadas para personalizar ainda mais a aparência e o comportamento do jogo em sua página.

Por padrão, o primeiro elemento canvas na página é usado para renderização. Para usar um elemento canvas diferente, a opção de substituição canvas pode ser usada. Ela requer uma referência ao próprio elemento DOM.

const canvasElement = document.querySelector("#my-canvas-element");
engine.startGame({ canvas: canvasElement });

A maneira como o motor redimensiona o canvas pode ser configurada por meio da opção de substituição canvasResizePolicy.

Se o seu jogo demorar um pouco para carregar, pode ser útil exibir uma interface de carregamento personalizada que rastreie o progresso. Isso pode ser alcançado com a opção de callback onProgress, que permite configurar uma função de callback que será chamada regularmente à medida que o motor carrega novos bytes.

function printProgress(current, total) {
    console.log("Loaded " + current + " of " + total + " bytes");
}
engine.startGame({ onProgress: printProgress });

Esteja ciente de que, em alguns casos, o total pode ser 0. Isso significa que ele não pode ser calculado.

Se o seu jogo suportar vários idiomas, a opção de substituição locale pode ser usada para forçar um idioma específico, desde que você tenha uma string de código de idioma válida. Pode ser bom usar uma lógica do lado do servidor para determinar quais idiomas o usuário prefere. Dessa forma, o código do idioma pode ser obtido do cabeçalho HTTP Accept-Language ou determinado por um serviço GeoIP.

Depuração

Para depurar projetos exportados, pode ser útil ler os fluxos de saída padrão (stdout) e de erro (stderr) gerados pelo motor. Isso é semelhante à saída mostrada na janela do console do editor. Por padrão, o console.log e o console.warn padrão são usados para os fluxos de saída e de erro, respectivamente. Esse comportamento pode ser personalizado definindo suas próprias funções para lidar com as mensagens.

Use a opção de substituição onPrint para definir uma função de callback para o fluxo de saída e a opção de substituição onPrintError para definir uma função de callback para o fluxo de erro.

function print(text) {
    console.log(text);
}
function printError(text) {
    console.warn(text);
}
engine.startGame({ onPrint: print, onPrintError: printError });

Ao lidar com a saída do motor, tenha em mente que pode não ser desejável exibi-la no produto final.