customizing_html5_shell.rst 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. :article_outdated: True
  2. .. _doc_customizing_html5_shell:
  3. Custom HTML page for Web export
  4. ====================================
  5. While Web export templates provide a default HTML page fully capable of launching
  6. the project without any further customization, it may be beneficial to create a custom
  7. HTML page. While the game itself cannot easily be directly controlled from the outside yet,
  8. such page allows to customize the initialization process for the engine.
  9. Some use-cases where customizing the default page is useful include:
  10. - Loading files from a different directory than the page;
  11. - Loading a ``.zip`` file instead of a ``.pck`` file as the main pack;
  12. - Loading the engine from a different directory than the main pack file;
  13. - Adding a click-to-play button so that games can be started in the fullscreen mode;
  14. - Loading some extra files before the engine starts, making them available in
  15. the project file system as soon as possible;
  16. - Passing custom command line arguments, e.g. ``-s`` to start a ``MainLoop`` script.
  17. The default HTML page is available in the Godot Engine repository at
  18. `/misc/dist/html/full-size.html <https://github.com/godotengine/godot/blob/master/misc/dist/html/full-size.html>`__
  19. but the following template can be used as a much simpler example:
  20. .. code-block:: html
  21. <!DOCTYPE html>
  22. <html>
  23. <head>
  24. <title>My Template</title>
  25. <meta charset="UTF-8">
  26. </head>
  27. <body>
  28. <canvas id="canvas"></canvas>
  29. <script src="$GODOT_URL"></script>
  30. <script>
  31. var engine = new Engine($GODOT_CONFIG);
  32. engine.startGame();
  33. </script>
  34. </body>
  35. </html>
  36. Setup
  37. -----
  38. As shown by the example above, it is mostly a regular HTML document, with few placeholders
  39. which needs to be replaced during export, an html ``<canvas>`` element, and some simple
  40. JavaScript code that calls the :js:class:`Engine` class.
  41. The only required placeholders are:
  42. - ``$GODOT_URL``:
  43. The name of the main JavaScript file, which provides the :js:class:`Engine` class required
  44. to start the engine and that must be included in the HTML as a ``<script>``.
  45. The name is generated from the *Export Path* during the export process.
  46. - ``$GODOT_CONFIG``:
  47. A JavaScript object, containing the export options and can be later overridden.
  48. See :js:attr:`EngineConfig` for the full list of overrides.
  49. The following optional placeholders will enable some extra features in your custom HTML template.
  50. - ``$GODOT_PROJECT_NAME``:
  51. The project name as defined in the
  52. :ref:`Name <class_ProjectSettings_property_application/config/name>` setting
  53. in **Project Settings > Application > Config**.
  54. It is a good idea to use it as a ``<title>`` in your template.
  55. - ``$GODOT_HEAD_INCLUDE``:
  56. A custom string to include in the HTML document just before the end of the ``<head>`` tag. It
  57. is customized in the export options under the *Html / Head Include* section. While you fully
  58. control the HTML page you create, this variable can be useful for configuring parts of the
  59. HTML ``head`` element from the Godot Editor, e.g. for different Web export presets.
  60. - ``$GODOT_SPLASH``:
  61. The path to the image used as the boot splash as defined in the
  62. :ref:`Image <class_ProjectSettings_property_application/boot_splash/image>` setting
  63. in **Project Settings > Application > Boot Splash**.
  64. - ``$GODOT_SPLASH_COLOR``
  65. The splash screen background color as defined in the
  66. :ref:`BG Color <class_ProjectSettings_property_application/boot_splash/bg_color>` setting
  67. in **Project Settings > Application > Boot Splash**, converted to a hex color code.
  68. When the custom page is ready, it can be selected in the export options under the *Html / Custom Html Shell*
  69. section.
  70. .. image:: img/html5_export_options.png
  71. Starting the project
  72. --------------------
  73. To be able to start the game, you need to write a script that initializes the engine — the control
  74. code. This process consists of three steps, but as shown here, most of them can be skipped depending on
  75. how much customization is needed.
  76. See the :ref:`HTML5 shell class reference <doc_html5_shell_classref>`, for the full list of methods and options available.
  77. First, the engine must be loaded, then it needs to be initialized, and after this the project
  78. can finally be started. You can perform every of these steps manually and with great control.
  79. However, in the simplest case all you need to do is to create an instance of the :js:class:`Engine`
  80. class with the exported configuration, and then call the :js:meth:`engine.startGame <Engine.prototype.startGame>` method
  81. optionally overriding any :js:attr:`EngineConfig` parameters.
  82. .. code-block:: js
  83. const engine = new Engine($GODOT_CONFIG);
  84. engine.startGame({
  85. /* optional override configuration, eg. */
  86. // unloadAfterInit: false,
  87. // canvasResizePolicy: 0,
  88. // ...
  89. });
  90. This snippet of code automatically loads and initializes the engine before starting the game.
  91. It uses the given configuration to load the engine. The :js:meth:`engine.startGame <Engine.prototype.startGame>`
  92. method is asynchronous and returns a ``Promise``. This allows your control code to track if
  93. the game was loaded correctly without blocking execution or relying on polling.
  94. In case your project needs to have special control over the start arguments and dependency files,
  95. the :js:meth:`engine.start <Engine.prototype.start>` method can be used instead. Note, that this method do not
  96. automatically preload the ``pck`` file, so you will probably want to manually preload it
  97. (and any other extra file) via the :js:meth:`engine.preloadFile <Engine.prototype.preloadFile>` method.
  98. Optionally, you can also manually :js:meth:`engine.init <Engine.prototype.init>` to perform specific actions after
  99. the module initialization, but before the engine starts.
  100. This process is a bit more complex, but gives you full control over the engine startup process.
  101. .. code-block:: js
  102. const myWasm = 'mygame.wasm';
  103. const myPck = 'mygame.pck';
  104. const engine = new Engine();
  105. Promise.all([
  106. // Load and init the engine
  107. engine.init(myWasm),
  108. // And the pck concurrently
  109. engine.preloadFile(myPck),
  110. ]).then(() => {
  111. // Now start the engine.
  112. return engine.start({ args: ['--main-pack', myPck] });
  113. }).then(() => {
  114. console.log('Engine has started!');
  115. });
  116. To load the engine manually the :js:meth:`Engine.load` static method must be called. As
  117. this method is static, multiple engine instances can be spawned if the share the same ``wasm``.
  118. .. note:: Multiple instances cannot be spawned by default, as the engine is immediately unloaded after it is initialized.
  119. To prevent this from happening see the :js:attr:`unloadAfterInit` override option. It is still possible
  120. to unload the engine manually afterwards by calling the :js:meth:`Engine.unload` static method. Unloading the engine
  121. frees browser memory by unloading files that are no longer needed once the instance is initialized.
  122. Customizing the behavior
  123. ------------------------
  124. In the Web environment several methods can be used to guarantee that the game will work as intended.
  125. If you target a specific version of WebGL, or just want to check if WebGL is available at all,
  126. you can call the :js:meth:`Engine.isWebGLAvailable` method. It optionally takes an argument that
  127. allows to test for a specific major version of WebGL.
  128. As the real executable file does not exist in the Web environment, the engine only stores a virtual
  129. filename formed from the base name of loaded engine files. This value affects the output of the
  130. :ref:`OS.get_executable_path() <class_OS_method_get_executable_path>` method and defines the name of
  131. the automatically started main pack. The :js:attr:`executable` override option can be
  132. used to override this value.
  133. Customizing the presentation
  134. ----------------------------
  135. Several configuration options can be used to further customize the look and behavior of the game on your page.
  136. By default, the first canvas element on the page is used for rendering. To use a different canvas
  137. element the :js:attr:`canvas` override option can be used. It requires a reference to the DOM
  138. element itself.
  139. .. code-block:: js
  140. const canvasElement = document.querySelector("#my-canvas-element");
  141. engine.startGame({ canvas: canvasElement });
  142. The way the engine resize the canvas can be configured via the :js:attr:`canvasResizePolicy`
  143. override option.
  144. If your game takes some time to load, it may be useful to display a custom loading UI which tracks
  145. the progress. This can be achieved with the :js:attr:`onProgress` callback option, which
  146. allows to set up a callback function that will be called regularly as the engine loads new bytes.
  147. .. code-block:: js
  148. function printProgress(current, total) {
  149. console.log("Loaded " + current + " of " + total + " bytes");
  150. }
  151. engine.startGame({ onProgress: printProgress });
  152. Be aware that in some cases ``total`` can be ``0``. This means that it cannot be calculated.
  153. If your game supports multiple languages, the :js:attr:`locale` override option can be used to
  154. force a specific locale, provided you have a valid language code string. It may be good to use server-side
  155. logic to determine which languages a user may prefer. This way the language code can be taken from the
  156. ``Accept-Language`` HTTP header, or determined by a GeoIP service.
  157. Debugging
  158. ---------
  159. To debug exported projects, it may be useful to read the standard output and error streams generated
  160. by the engine. This is similar to the output shown in the editor console window. By default, standard
  161. ``console.log`` and ``console.warn`` are used for the output and error streams respectively. This
  162. behavior can be customized by setting your own functions to handle messages.
  163. Use the :js:attr:`onPrint` override option to set a callback function for the output stream,
  164. and the :js:attr:`onPrintError` override option to set a callback function for the error stream.
  165. .. code-block:: js
  166. function print(text) {
  167. console.log(text);
  168. }
  169. function printError(text) {
  170. console.warn(text);
  171. }
  172. engine.startGame({ onPrint: print, onPrintError: printError });
  173. When handling the engine output, keep in mind that it may not be desirable to print it out in the
  174. finished product.