Engine guide
HTML5
Canvas / WebGL, zero framework
If your game is pure HTML / Canvas / WebGL (no framework, no build step), the SDK is a single script tag and three function calls. This page shows the full integration — copy + adapt.
1. Include the SDK
<script src="https://pixlland.com/sdk/v1/pixlland.js" defer></script>Keep defer so the script never blocks first paint. The file is ~8 KB IIFE.
2. Wire the boot sequence
const SDK = window.PixllandSDK;
async function boot() {
const { gameId, signedIn, locale } = await SDK.init({
onError: console.warn,
});
console.log('booted as', gameId, 'locale=', locale);
// Assets (images, audio, level data) loading in parallel
await Promise.all([
loadImage('/assets/hero.png', (p) => SDK.gameLoadingProgress(p * 0.5)),
loadSounds(/* … */).then(() => SDK.gameLoadingProgress(0.9)),
]);
SDK.gameLoadingFinished();
attachClickHandlers();
}
boot();3. Frame loop
happyTime is the portal's primary engagement metric — call it once per animation frame when gameplay is actually running.
let last = performance.now();
function tick(now) {
const dt = (now - last) / 1000; // seconds
last = now;
if (inGameplay) {
update(dt);
draw();
SDK.happyTime(dt);
}
requestAnimationFrame(tick);
}
requestAnimationFrame(tick);4. Gameplay flags
function onStartButton() {
SDK.gameplayStart();
inGameplay = true;
}
function onDeath() {
SDK.gameplayStop();
inGameplay = false;
// Async so the "You died" UI has time to paint first:
setTimeout(async () => {
await SDK.commercialBreak();
showRestartMenu();
}, 1200);
}5. Save game state
async function saveProgress() {
try {
await SDK.data.set('progress', {
level: state.level,
coins: state.coins,
unlocks: [...state.unlocks],
});
} catch (e) {
SDK.captureError(e);
}
}
// Resume on boot if the player is signed in
const saved = await SDK.data.get('progress');
if (saved) applyProgress(saved);Common pitfalls
- Requiring WebAudio before a user gesture. Desktop Chrome/Safari block audio until the first click. Put the first
audioContext.resume()inside your Play button handler, not insideinit(). - Fullscreen without user activation.
requestFullscreenmust be called from a synchronous click handler. Resolve the ad break first, then request fullscreen in a subsequent tap. - Calling
commercialBreakon every frame. The portal doesn't rate-limit you — your players will leave. Target ~1 break per 90 seconds of gameplay.
Reference sample
The starter template (scaffolded by pixlland init) is the shortest integration that exercises every call on this page.
