Engine guide
Defold
Lua-based, tiny runtime (~3 MB)
Defold ships a custom HTML5 build template + an html5.js Lua API for interop. The SDK is one script tag in the template plus a Lua helper module.
1. Custom HTML5 build template
Copy /builtins/manifests/web/engine_template.html into your project root, rename, and set game.project → html5 → htmlfile. Add to <head>:
<script src="https://pixlland.com/sdk/v1/pixlland.js" defer></script>2. Lua helper module
Save as main/pixlland.lua:
local M = {}
local function js(src)
if html5 then html5.run(src) end
end
function M.init()
js([[ window.PixllandSDK && window.PixllandSDK.init(); ]])
end
function M.loading_finished()
js([[ window.PixllandSDK && window.PixllandSDK.gameLoadingFinished(); ]])
end
function M.gameplay_start()
js([[ window.PixllandSDK && window.PixllandSDK.gameplayStart(); ]])
end
function M.gameplay_stop()
js([[ window.PixllandSDK && window.PixllandSDK.gameplayStop(); ]])
end
function M.happy_time(delta)
js(string.format([[ window.PixllandSDK && window.PixllandSDK.happyTime(%f); ]], delta))
end
-- commercial_break resolves when the JS promise fires. We poll a flag
-- written by the JS callback — 50ms ticks are fine for Defold's loop.
function M.commercial_break(callback)
if not html5 then callback() return end
html5.run([[
window.__pll_ad_done = false;
window.PixllandSDK.commercialBreak().then(function(){
window.__pll_ad_done = true;
});
]])
timer.delay(0.05, true, function(self, handle, _)
local done = html5.run([[ window.__pll_ad_done ? "1" : "0" ]])
if done == "1" then
timer.cancel(handle)
callback()
end
end)
end
return M3. Wire into your main script
local pixlland = require "main.pixlland"
function init(self)
pixlland.init()
pixlland.loading_finished()
pixlland.gameplay_start()
self.in_game = true
end
function update(self, dt)
if self.in_game then pixlland.happy_time(dt) end
end
function on_player_died(self)
pixlland.gameplay_stop()
self.in_game = false
pixlland.commercial_break(function()
msg.post("#", "restart_level")
end)
endCommon pitfalls
- html5 module is nil outside web builds. Always guard — the wrapper above no-ops cleanly so you can test the rest of your game in the editor.
- Polling
html5.runburns a frame of latency. For 1 commercial break per 90 seconds this is a non-issue; if you chain them, batch via a single callback.
