导出自定义HTML页面

While Web export templates provide a default HTML page fully capable of launching the project without any further customization, it may be beneficial to create a custom HTML page. While the game itself cannot easily be directly controlled from the outside yet, such page allows to customize the initialization process for the engine.

自定义默认页面有用的一些用例包括:

  • 从其他目录加载文件;

  • 加载 .zip 文件而不是 .pck 文件作为主资源包;

  • 从主资源包文件以外的目录中加载引擎文件;

  • 添加一个”即点即玩”按钮,使游戏可以在全屏模式下启动;

  • 在引擎启动之前加载一些额外的文件,以便稍后在文件系统中可用;

  • 传递自定义”命令行”参数,例如 -s 启动``MainLoop``脚本.

The default HTML page is available in the Godot Engine repository at /misc/dist/html/full-size.html but the following template can be used as a much simpler example:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>My Template</title>
  5. <meta charset="UTF-8">
  6. </head>
  7. <body>
  8. <canvas id="canvas"></canvas>
  9. <script src="$GODOT_URL"></script>
  10. <script>
  11. var engine = new Engine($GODOT_CONFIG);
  12. engine.startGame();
  13. </script>
  14. </body>
  15. </html>

场景布置

As shown by the example above, it is mostly a regular HTML document, with few placeholders which needs to be replaced during export, an html <canvas> element, and some simple JavaScript code that calls the Engine() class.

The only required placeholders are:

  • $GODOT_URL: The name of the main JavaScript file, which provides the Engine() class required to start the engine and that must be included in the HTML as a <script>. The name is generated from the Export Path during the export process.

  • $GODOT_CONFIG: A JavaScript object, containing the export options and can be later overridden. See EngineConfig for the full list of overrides.

The following optional placeholders will enable some extra features in your cusstom HTML template.

  • $GODOT_PROJECT_NAME: The project name as defined in the Project Settings. It is a good idea to use it as a <title> in your template.

  • $GODOT_HEAD_INCLUDE.在HTML文件中,在``<head>``标签结尾前包含的一个自定义字符串.它是在*Html / Head Include*部分的导出选项中自定义的.虽然你可以完全控制你所创建的HTML页面,但这个变量对于从Godot Editor中配置HTML``head``元素的部分内容很有用,例如,对于不同的Web导出预设.

当自定义页面准备好后,可以在 Html / Custom Html Shell 部分的导出选项中选择.

../../_images/html5_export_options.png

启动项目

To be able to start the game, you need to write a script that initializes the engine — the control code. This process consists of three steps, though as shown most of them can be skipped depending on how much customization is needed (or be left to a default behavior).

See the HTML5 shell class reference, for the full list of methods and options available.

First, the engine must be loaded, then it needs to be initialized, and after this the project can finally be started. You can perform every of these steps manually and with great control. However, in the simplest case all you need to do is to create an instance of the Engine() class with the exported configuration, and then call the engine.startGame method optionally overriding any EngineConfig parameters.

  1. const engine = new Engine($GODOT_CONFIG);
  2. engine.startGame({
  3. /* optional override configuration, eg. */
  4. // unloadAfterInit: false,
  5. // canvasResizePolicy: 0,
  6. // ...
  7. });

This snippet of code automatically loads and initializes the engine before starting the game. It uses the given configuration to to load the engine. The engine.startGame method is asynchronous and returns a Promise. This allows your control code to track if the game was loaded correctly without blocking execution or relying on polling.

In case your project needs to have special control over the start arguments and dependency files, the engine.start method can be used instead. Note, that this method do not automatically preload the pck file, so you will probably want to manually preload it (and any other extra file) via the engine.preloadFile method.

Optionally, you can also manually engine.init to perform specific actions after the module initialization, but before the engine starts.

This process is a bit more complex, but gives you full control over the engine startup process.

  1. const myWasm = 'mygame.wasm';
  2. const myPck = 'mygame.pck';
  3. const engine = new Engine();
  4. Promise.all([
  5. // Load and init the engine
  6. engine.init(myWasm),
  7. // And the pck concurrently
  8. engine.preloadFile(myPck),
  9. ]).then(() => {
  10. // Now start the engine.
  11. return engine.start({ args: ['--main-pack', myPck] });
  12. }).then(() => {
  13. console.log('Engine has started!');
  14. });

To load the engine manually the Engine.load() static method must be called. As this method is static, multiple engine instances can be spawned if the share the same wasm.

注解

Multiple instances cannot be spawned by default, as the engine is immediately unloaded after it is initialized. To prevent this from happening see the unloadAfterInit override option. It is still possible to unload the engine manually afterwards by calling the Engine.unload() static method. Unloading the engine frees browser memory by unloading files that are no longer needed once the instance is initialized.

自定义行为

在Web环境下,可以使用几种方法来保证游戏能够按照预期的方式运行.

如果您的目标是WebGL的特定版本,或者只是想检查WebGL是否可用,您可以调用 Engine.isWebGLAvailable() 方法.它可以选择接受一个参数,允许测试WebGL的特定主要版本.

As the real executable file does not exist in the Web environment, the engine only stores a virtual filename formed from the base name of loaded engine files. This value affects the output of the OS.get_executable_path() method and defines the name of the automatically started main pack. The executable override option can be used to override this value.

自定义演示文稿

Several configuration options can be used to further customize the look and behavior of the game on your page.

By default, the first canvas element on the page is used for rendering. To use a different canvas element the canvas override option can be used. It requires a reference to the DOM element itself.

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

The way the engine resize the canvas can be configured via the canvasResizePolicy override option.

If your game takes some time to load, it may be useful to display a custom loading UI which tracks the progress. This can be achieved with the onProgress callback option, which allows to set up a callback function that will be called regularly as the engine loads new bytes.

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

请注意,在某些情况下, total 可能是 0 .这意味着无法计算.

If your game supports multiple languages, the locale override option can be used to force a specific locale, provided you have a valid language code string. It may be good to use server-side logic to determine which languages a user may prefer. This way the language code can be taken from the Accept-Language HTTP header, or determined by a GeoIP service.

调试

要调试导出的项目,可能需要读取引擎生成的标准输出和错误流.这与编辑器控制台窗口中显示的输出类似.默认情况下,标准的 console.logconsole.warning 分别用于输出和错误流.这种行为可以通过设置自己的函数来处理消息来定制.

Use the onPrint override option to set a callback function for the output stream, and the onPrintError override option to set a callback function for the error stream.

  1. function print(text) {
  2. console.log(text);
  3. }
  4. function printError(text) {
  5. console.warn(text);
  6. }
  7. engine.startGame({ onPrint: print, onPrintError: printError });

When handling the engine output keep in mind, that it may not be desirable to print it out in the finished product.