Pixlland

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 M

3. 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)
end

Common 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.run burns 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.
Defold · Pixlland Engines