Pixlland

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 inside init().
  • Fullscreen without user activation. requestFullscreen must be called from a synchronous click handler. Resolve the ad break first, then request fullscreen in a subsequent tap.
  • Calling commercialBreak on 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.

Vanilla HTML5 · Pixlland Engines