customizing_html5_shell.rst 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. .. _doc_customizing_html5_shell:
  2. Custom HTML page for Web export
  3. ====================================
  4. While Web export templates provide a default HTML page fully capable of launching
  5. the project without any further customization, it may be beneficial to create a custom
  6. HTML page. While the game itself cannot be directly controlled from the outside,
  7. such page allows to customize the initialization process for the engine.
  8. Some use-cases where customizing the default page is useful include:
  9. - Loading files from a different directory than the page;
  10. - Loading a ``.zip`` file instead of a ``.pck`` file as the main pack;
  11. - Loading the engine from a different directory than the main pack file;
  12. - Adding a click-to-play button so that games can be started in the fullscreen mode;
  13. - Loading some extra files before the engine starts, making them available in
  14. the project file system as soon as possible;
  15. - Passing custom command line arguments, e.g. ``-s`` to start a ``MainLoop`` script.
  16. The default HTML page is available in the Godot Engine repository at
  17. `/misc/dist/html/full-size.html <https://github.com/godotengine/godot/blob/3.2/misc/dist/html/full-size.html>`__
  18. and can be used as a reference implementation. Another sample HTML page is available at
  19. `/misc/dist/html/fixed-size.html <https://github.com/godotengine/godot/blob/3.2/misc/dist/html/fixed-size.html>`__.
  20. It differs from the default one by having a fixed size canvas area and an output widget below it.
  21. .. note:: It is recommended to use developer tools provided by browser vendors to debug
  22. exported projects. Output generated by the engine may be limited and does not
  23. include WebGL errors.
  24. Setup
  25. -----
  26. As evident by the default HTML page, it is mostly a regular HTML document. To work with
  27. Godot projects it needs to be fully realized, to have a control code that calls
  28. the :js:class:`Engine` class, and to provide places for several placeholders, which are
  29. replaced with their actual values during export.
  30. .. image:: img/html5_export_options.png
  31. - ``$GODOT_BASENAME``:
  32. The base name from the *Export Path*, as set up in the export options; suffixes are omitted
  33. (e.g. ``game.html`` becomes ``game``). This variable can be used to generate a path
  34. to the main JavaScript file ``$GODOT_BASENAME.js``, which provides the :js:class:`Engine`
  35. class. A splash image shown during the booting process can be accessed using this variable
  36. as well: ``$GODOT_BASENAME.png``.
  37. - ``$GODOT_PROJECT_NAME``:
  38. The project name as defined in the Project Settings.
  39. - ``$GODOT_HEAD_INCLUDE``:
  40. A custom string to include in the HTML document just before the end of the ``<head>`` tag. It
  41. is customized in the export options under the *Html / Head Include* section. While you fully
  42. control the HTML page you create, this variable can be useful for configuring parts of the
  43. HTML ``head`` element from the Godot Editor, e.g. for different Web export presets.
  44. - ``$GODOT_DEBUG_ENABLED``:
  45. A flag that tells if this is a debug build, or not. This variable is substituted by strings
  46. ``true`` and ``false``, and can be used to disable debug branches within your control code.
  47. When the custom page is ready, it can be selected in the export options under the *Html / Custom Html Shell*
  48. section.
  49. Starting the project
  50. --------------------
  51. To be able to start the game, you need to write a script that initializes the engine — the control
  52. code. This process consists of three steps, though some of them can be skipped and left for
  53. a default behavior.
  54. First, the engine must be loaded, then it needs to be initialized, and after this the project
  55. can finally be started. You can perform every of these steps manually and with great control.
  56. However, in the simplest case all you need to do is to create an instance of the :js:class:`Engine`
  57. class and then call the :js:meth:`engine.startGame` method.
  58. .. code-block:: js
  59. const execName = "path://to/executable"
  60. const mainPack = "path://to/main_pack"
  61. const engine = new Engine();
  62. engine.startGame(execName, mainPack)
  63. This snippet of code automatically loads and initializes the engine before starting the game.
  64. It uses the given path to the executable to deduce the path to load the engine. The :js:meth:`engine.startGame`
  65. method is asynchronous and returns a ``Promise``. This allows your control code to track if
  66. the game was loaded correctly without blocking execution or relying on polling.
  67. In case your project needs to have special arguments passed to it by the start-up script,
  68. :js:meth:`engine.startGame` can be replaced by :js:meth:`engine.start`. This method takes an
  69. arbitrary list of string arguments. As it does not have a defined list of arguments, :js:meth:`engine.start`
  70. cannot automatically load the engine.
  71. To load the engine manually the :js:meth:`Engine.load` static method must be called. As
  72. this method is static, multiple engine instances can be spawned with the exact same ``basePath``.
  73. If an instance requires a different ``basePath``, you can call the :js:meth:`engine.init`
  74. method with that path before starting the game.
  75. .. note:: Multiple instances cannot be spawned by default, as the engine is immediately unloaded after it is initialized.
  76. To prevent this from happening the :js:meth:`engine.setUnloadAfterInit` method can be called. It is still possible
  77. to unload the engine manually afterwards by calling the :js:meth:`Engine.unload` static method. Unloading the engine
  78. frees browser memory by unloading files that are no longer needed once the instance is initialized.
  79. To correctly load the engine on some hosting providers and network configurations you may
  80. need to change the default filename extension by using :js:meth:`Engine.setWebAssemblyFilenameExtension`.
  81. By default, the extension is assumed to be ``wasm``. If your hosting provider blocks this
  82. extension, this static method can be used to change it to something that is supported.
  83. .. code-block:: js
  84. Engine.setWebAssemblyFilenameExtension("dat");
  85. // Load mygame.dat as WebAssembly module.
  86. Engine.load("mygame");
  87. .. warning:: If a different filename extension is used, some web servers may automatically
  88. set the MIME-type of the file to something other than :mimetype:`application/wasm`.
  89. In that case some start-up optimizations may be skipped.
  90. Customizing the behavior
  91. ------------------------
  92. In the Web environment several methods can be used to guarantee that the game will work as intended.
  93. If you target a specific version of WebGL, or just want to check if WebGL is available at all,
  94. you can call the :js:meth:`Engine.isWebGLAvailable` method. It optionally takes an argument that
  95. allows to test for a specific major version of WebGL.
  96. As the real executable file does not exist in the Web environment, the engine only stores a virtual
  97. filename formed from the base name of loaded engine files. This value affects the output of the
  98. :ref:`OS.get_executable_path() <class_OS_method_get_executable_path>` method and defines the name of
  99. the automatically started main pack. The :js:meth:`engine.setExecutableName` method can be used
  100. to override this value.
  101. If your project requires some files to be available the moment it is loaded, you can preload
  102. them by calling the :js:meth:`engine.preloadFile` method with a path to a file or by providing it
  103. with an ``ArrayBuffer`` object. In case of the ``ArrayBuffer``, or one of its views, a second argument
  104. must be specified to define an internal path for the loaded resource.
  105. Customizing the presentation
  106. ----------------------------
  107. Several methods can be used to further customize the look and behavior of the game on your page.
  108. By default, the first canvas element on the page is used for rendering. To use a different canvas
  109. element the :js:meth:`engine.setCanvas` method can be used. It requires a reference to the DOM
  110. element itself.
  111. .. code-block:: js
  112. const canvasElement = document.querySelector("#my-canvas-element");
  113. engine.setCanvas(canvasElement);
  114. If the width and height of this canvas element differ from values set in the project settings, it
  115. will be resized on the project start. This behavior can be disabled by calling the :js:meth:`engine.setCanvasResizedOnStart`
  116. method.
  117. If your game takes some time to load, it may be useful to display a custom loading UI which tracks
  118. the progress. This can be achieved with the :js:meth:`engine.setProgressFunc` method which allows
  119. to set up a callback function to be called regularly as the engine loads new bytes.
  120. .. code-block:: js
  121. function printProgress(current, total) {
  122. console.log("Loaded " + current + " of " + total + " bytes");
  123. }
  124. engine.setProgressFunc(printProgress);
  125. Be aware that in some cases ``total`` can be ``0``. This means that it cannot be calculated.
  126. If your game supports multiple languages, the :js:meth:`engine.setLocale` method can be used to set
  127. a specific locale, provided you have a valid language code string. It may be good to use server-side
  128. logic to determine which languages a user may prefer. This way the language code can be taken from the
  129. ``Accept-Language`` HTTP header, or determined by a GeoIP service.
  130. Debugging
  131. ---------
  132. To debug exported projects, it may be useful to read the standard output and error streams generated
  133. by the engine. This is similar to the output shown in the editor console window. By default, standard
  134. ``console.log`` and ``console.warn`` are used for the output and error streams respectively. This
  135. behavior can be customized by setting your own functions to handle messages.
  136. Use the :js:meth:`engine.setStdoutFunc` method to set a callback function for the output stream. Default
  137. behavior is similar to this:
  138. .. code-block:: js
  139. function printStdout(text) {
  140. console.log(text);
  141. }
  142. engine.setStdoutFunc(printStdout);
  143. Use the :js:meth:`engine.setStderrFunc` method to set a callback function for the error stream. Default
  144. behavior is similar to this:
  145. .. code-block:: js
  146. function printStderr(text) {
  147. console.warn("Error: " + text);
  148. }
  149. engine.setStderrFunc(printStderr);
  150. When handling the engine output keep in mind, that it may not be desirable to print it out in the
  151. finished product. To control whether or not the current execution is actually a debug build you can
  152. use ``$GODOT_DEBUG_ENABLED`` placeholder.
  153. Further debugging options and a low level access to the execution environment are available in a form
  154. of Emscripten's ``Module`` object. It can be accessed using the :js:attr:`engine.rtenv` property on the
  155. engine instance.