Defold supports building games for the HTML5 platform through the regular bundling menu, as well as for other platforms. In addition, the resulting game is embedded on a regular HTML page that can be styled through a simple template system.
The game.project file contains the HTML5 specific settings:
Defold support for HTML5 is powered by Emscripten (See http://en.wikipedia.org/wiki/Emscripten). In short, it creates a sandbox of memory for the heap in which the application operates. By default, the engine allocates a generous amount of memory (256MB). This should be more than sufficient for the typical game. As part of your optimization process, you may choose to use a smaller value. To do this, follow these steps:
For testing, HTML5 build needs an HTTP server. Defold creates one for you if you choose Project ▸ Build HTML5.
If you want to test your bundle, just upload it to your remote HTTP server or create a local server, for example, using python in the bundle folder. Python 2:
python -m SimpleHTTPServer
Python 3:
python -m http.server
or
python3 -m http.server
You can’t test the HTML5 bundle by opening index.html
file in a browser. This requires HTTP server.
If you see a “wasm streaming compile failed: TypeError: Failed to execute ‘compile’ on ‘WebAssembly’: Incorrect response MIME type. Expected ‘application/wasm’.” error in the console you must make sure that your server uses the application/wasm
MIME type for .wasm files.
Creating HTML5 content with Defold is simple and follows the same pattern as all other supported platforms: select Project ▸ Bundle... ▸ HTML5 Application... from the menu:
You can chose to include both an asm.js
and a WebAssembly (wasm) version of the Defold engine in HTML5 bundle. In most cases it is enough to chose WebAssembly since all modern browsers support WebAssembly.
Even if you include both asm.js
and wasm
versions of the engine only one of them will be downloaded by the browser when launching the game. The WebAssembly version will be downloaded if the browser supports WebAssembly and the asm.js version will be used as a fallback in the rare case that WebAssembly is not supported.
When you click on the Create bundle button you will be prompted to select a folder in which to create your application. After the export process completes, you will find all of the files needed to run the application.
--verify-graphics-calls=false
.When generating an HTML5 version of your game, Defold provides a default web page. It references style and script resources that dictate how your game is presented.
Each time the application is exported, this content is created afresh. If you wish to customize any of these elements you must make modifications to your project settings. To do so, open the game.project in the Defold editor and scroll to the html5 section:
More information about every option is available in project settings manual.
You can’t modify files of the default html/css template in builtins
folder. For applying your modifications copy/paste needed file from builtins
and set this file in game.project.
The canvas shouldn’t be styled with any border or padding. If you do, mouse input coordinates will be wrong.
In game.project it is possible to turn-off the Fullscreen
button and the Made with Defold
link.
Defold provides a dark and light theme for the index.html. The light theme is set by default but it is possible to change by changing Custom CSS
file. There is also four predefined scale modes to chose from in the Scale Mode
field.
The calculations for all scale modes include current screen DPI in case if you turn on High Dpi
option in game.project (Display
section)
For the Fit
mode canvas size will be changed to show full game canvas on the screen with original proportions. The only difference in Downscale Fit
is changing size only if the inner size of the webpage is smaller than the original canvas of the game, but doesn’t scale-up when a webpage is bigger than the original game canvas.
For the Stretch
mode canvas size will be changed to fully fill the inner size of the webpage.
With No Scale
mode the canvas size is exactly the same as you predefined in game.project file, [display]
section.
We use Mustache template language for creation of the index.html
file. When your are building or bundling, the HTML and CSS files are passed through a compiler that is capable of replacing certain tokens with values that depend upon your project settings. These tokens are always encased in either double or triple curly braces ({{TOKEN}}
or {{{TOKEN}}}
), depending on whether character sequences should be escaped or not. This feature can be useful if you either make frequent changes to your project settings or intend for material to be reused in other projects.
More information about Mustache template language is available in manual.
Any game.project can be a token. For example, if you want to use Width
value from Display
section:
Open game.project as a text and check [section_name]
and name of the field you want to use. Then you can use it as a token: {{section_name.field}}
or {{{section_name.field}}}
.
For example, in HTML template in JavaScript:
function doSomething() {
var x = {{display.width}};
// ...
}
Also, we have the following custom tokens:
false
if html5.splash_image
in game.project is empty{{#DEFOLD_SPLASH_IMAGE}}
background-image: url("{{DEFOLD_SPLASH_IMAGE}}");
{{/DEFOLD_SPLASH_IMAGE}}
<style>
{{{DEFOLD_CUSTOM_CSS_INLINE}}}
</style>
It is important that this inline block appear before the main application script is loaded. Since it includes HTML tags, this macro should appear in triple braces {{{TOKEN}}}
to prevent character sequences being escaped.
true
if html5.scale_mode
is Downscale Fit
.true
if html5.scale_mode
is Fit
.true
if html5.scale_mode
is No Scale
.true
if html5.scale_mode
is Stretch
.html5.heap_size
converted to bytes.html5.engine_arguments
separated by ,
symbol.If you create your custom template, you can redefine set of parameters for the engine loader. To achieve that you need to add <script>
section and redefine values inside CUSTOM_PARAMETERS
.
Your custom <script>
should be placed after <script>
section with reference to dmloader.js but before call EngineLoader.load
function.
For example:
<script id='custom_setup' type='text/javascript'>
CUSTOM_PARAMETERS['disable_context_menu'] = false;
CUSTOM_PARAMETERS['unsupported_webgl_callback'] = function() {
console.log("Oh-oh. WebGL not supported...");
}
</script>
CUSTOM_PARAMETERS
may contains following fields:
'archive_location_filter':
Filter function that will run for each archive path.
'unsupported_webgl_callback':
Function that is called if WebGL is not supported.
'engine_arguments':
List of arguments (strings) that will be passed to the engine.
'custom_heap_size':
Number of bytes specifying the memory heap size.
'disable_context_menu':
Disables the right-click context menu on the canvas element if true.
'retry_time':
Pause in seconds before retry file loading after error.
'retry_count':
How many attempts we do when trying to download a file.
'can_not_download_file_callback':
Function that is called if you can't download file after 'retry_count' attempts.
'resize_window_callback':
Function that is called when resize/orientationchanges/focus events happened
HTML5 builds support file operations such as sys.save()
, sys.load()
and io.open()
but the way these operations are handled internally is different from other platforms. When Javascript is run in a browser there is no real concept of a file system and local file access is blocked for security reasons. Instead Emscripten (and thus Defold) uses IndexedDB, an in-browser database used to persistently store data, to create a virtual filesystem in the browser. The important difference from file system access on other platforms is that there can be a slight delay between writing to a file and the change actually being stored in the database. The browser developer console usually allows you to inspect the contents of the IndexedDB.
It is sometimes necessary to provide additional arguments to a game before it or as it is started. This could for instance be a user id, session token or which level to load when the game starts. This can be achieved in a number of different ways, some of which are described here.
It is possible to specify additional engine arguments when the engine is configured and loaded. These extra engine arguments can at runtime be retrieved using sys.get_config()
. To add the key-value pairs you modify the engine_arguments
field of the extra_params
object that is passed to the engine when loaded in index.html
:
<script id='engine-setup' type='text/javascript'>
var extra_params = {
...,
engine_arguments: ["–config=foo1=bar1","--config=foo2=bar2"],
...
}
You can also add "–config=foo1=bar1","--config=foo2=bar2"
to the engine arguments field in the HTML5 section of game.project and it will be injected into the generated index.html file.
At runtime you get the values like this:
local foo1 = sys.get_config("foo1")
local foo2 = sys.get_config("foo2")
print(foo1) -- bar1
print(foo2) -- bar2
You can pass arguments as part of the query parameters in the page URL and read these at runtime:
https://www.mygame.com/index.html?foo1=bar1&foo2=bar2
local url = html5.run("window.location")
print(url)
A full helper function to get all query parameters as a Lua table:
local function get_query_parameters()
local url = html5.run("window.location")
-- get the query part of the url (the bit after ?)
local query = url:match(".*?(.*)")
if not query then
return {}
end
local params = {}
-- iterate over all key value pairs
for kvp in query:gmatch("([^&]+)") do
local key, value = kvp:match("(.+)=(.+)")
params[key] = value
end
return params
end
function init(self)
local params = get_query_parameters()
print(params.foo1) -- bar1
end
HTML5 games usually have strict requirements on initial download size, startup time and memory usage to ensure that games load fast and run well on low end devices and slow internet connections. To optimize an HTML5 game it is recommended to focus on the following areas:
A: In some cases it is not possible to run a game in the browser locally from the filesystem. Running from the editor serves the game from a local web server. You can, for instance, use SimpleHTTPServer in Python:
$ python -m SimpleHTTPServer [port]
A: This usually happens when you are using Windows and make a build and commit it to Git. If you have the wrong line-ending configuration in Git it will change your line endings and thus also the data size. Follow these instructions to solve the problem: https://docs.github.com/en/free-pro-team@latest/github/using-git/configuring-git-to-handle-line-endings
Did you spot an error or do you have a suggestion? Please let us know on GitHub!
GITHUB