Weezdraw Game SDK 2
The SDK connects your HTML5 game to Weezdraw: it reports each game's result, gives every player of a competition the same random numbers, and lets the platform pause or mute your game. It is a single script with no dependencies (about 5 KB gzipped). It works with any web game engine (plain JS, Phaser, PixiJS, Three.js, Construct…); a Unity WebGL build can call window.WZ from a .jslib plugin.
1. Quick start
Add the SDK to the <head> of your index.html:
<script src="https://weezdraw-sdk.vercel.app/sdk/v2/weezdraw-sdk.js"></script>Then, in your game code:
await WZ.init(); // once, at startup
// when the player presses Play:
const start = await WZ.gameplayStart();
if (!start.allowed) showNoMoreGamesScreen();
// when the game is over (all lives lost, level won, time out…):
await WZ.points(finalScore); // or WZ.time(ms) / WZ.composite(score, parts)That is all a game needs. Prefer a single self-contained index.html? Paste the ready-to-paste SDK block once in your <head>, without editing it. TypeScript users: get the type definitions.
2. Game lifecycle
const ctx = await WZ.init(); // { mode, competition, seed, attemptsLeft, params, … }
WZ.loading(40); // optional: loading progress 0–100
WZ.ready(); // loaded, the menu is showing
const start = await WZ.gameplayStart(); // the player starts playing
// … during play, optionally every time the score changes:
WZ.progress(score);
await WZ.points(score); // the game is over- mode tells you where the game runs:
competition(results count),free(casual play),sandbox(your preview) orstandalone(opened directly, e.g. on your computer). Your game plays the same way in all of them. - gameplayStart() opens the game on the Weezdraw server. In a competition this uses one of the player's attempts; if none is left,
allowedis false. - progress() is optional but recommended: it keeps the game alive on the server and records the live score. In a competition it is also the score that counts if the player leaves the game (see below): without it, a player who leaves scores 0.
- No pause in a competition. If the game page stays hidden (another tab or app, a phone call) for 10 seconds in total during a game (all absences add up), the game is over: the platform ends it on the server with the last score sent with
progress()(0 if none), and a result reported later is refused. Coming back within 10 seconds changes nothing. Free play is not concerned. - params are settings Weezdraw can set per competition (for example a difficulty level).
3. Reporting results
WZ.points(1250); // higher is better (most games)
WZ.time(38740); // lower is better, in milliseconds
WZ.composite(total, { points: 950, coins: 15 }); // your own blend, higher is betterEach call returns a promise that resolves once Weezdraw confirmed the result (the SDK resends it automatically until then, and the server counts it only once). WZ.gameOver(score) is an alias of WZ.points. Endless games: call the result when the player stops, and wire a “Done” button to WZ.finish().
4. Fair randomness
In a competition, every player must face the same luck. Use the SDK's random functions instead of Math.random() for anything that affects the game (level layout, enemy spawns, card order…):
WZ.random(); // number in [0, 1)
WZ.randomInt(1, 6); // integer from 1 to 6
WZ.randomRange(0, 360); // float between 0 and 360The sequence restarts at each gameplayStart(): every player's first game gets the same numbers, every second game the same other numbers, and so on.
One sequence per part of the game. When several parts of your game draw random numbers, give each its own named sequence: what one part draws (more particles on a fast device, for example) then never shifts another.
const level = WZ.stream("level");
const enemies = WZ.stream("enemies");
level.randomInt(0, 9); // same for every player
enemies.random(); // independent of the level's drawsEquity is Weezdraw's rule: the SDK also ties Math.random() to the shared seed, so a game that forgot WZ.random still gives every player the same randomness. Using WZ.random or WZ.stream for everything that changes the game remains the right way.
5. Pause and sound
WZ.on("pause", () => game.pause());
WZ.on("resume", () => game.resume());
WZ.on("mute", () => audio.mute());
WZ.on("unmute", () => audio.unmute());If your game handles pause, Weezdraw pauses it when the player leaves the page (a phone call, another app) and resumes it when they come back. Otherwise, in free play, the page stops the game to guarantee silence, and the player loses the game in progress. In a competition the page is never torn down for a short absence, but a game hidden for more than 10 seconds is over (no pause in a competition).
Auto start (SDK 2.1)
In a competition every player must start together, so Weezdraw starts the game itself: it shows your rules and a 3-2-1 countdown while the game loads, then says start. When the context says autoStart, skip your title screen and begin playing on that signal:
const ctx = await WZ.init();
if (ctx.autoStart) {
WZ.on("start", () => startGame()); // no Play button: Weezdraw starts the game
} else {
showTitleScreen(); // free play: the player presses Play
}A start sent before your game listens is kept until it does. A game that does not listen for start still works: the player presses its Play button.
6. Rules for competitions (required to go live)
- One game = one result. If your game has several lives, report the result only when the last life is lost (or the level is won, or time runs out), never after each life.
- Report on every way a game can end.
- Points and composite scores are integers. Times are in milliseconds.
- The reported value must match what the player sees on your game-over screen.
- Use the SDK's random functions for everything that affects the score.
- Do not start a new scored game on your own: call
WZ.gameplayStart()and respectallowed. A game left in the middle still counts as played. - A game lasts 3 minutes at most (shorter is fine): show a timer or end naturally. In a competition the platform ends a game still running at 3 minutes, with its last live score.
- Start on Weezdraw's signal (
WZ.on("start")): no title screen, menu or demo in competitions. - Send the live score with
WZ.progress(score): it counts if a player leaves or loses the connection. - Add bonus points (precision, time left, level reached) so that equal scores are rare.
- Handle
WZ.on("mute")andWZ.on("unmute"). - Your game must be fully contained in the ZIP: no ads, trackers, external fonts or libraries, redirects or pop-ups, and no purchase, continue or replay button.
- Skill decides the result. Before review, Weezdraw's robot players test your game: untrained robots and a robot that learns the game play the same unseen games. If playing better does not pay off, the game cannot be used in competitions. Weezdraw validates every game by hand.
- Declare the possible score range in a
manifest.jsonat the root of your ZIP, e.g.{"minScore": 0, "maxScore": 5000}: results outside it are refused as impossible.
7. No-code integration (bridge)
Can't change a game's code (an exported build, a licensed game)? Describe it instead, on your game's page in the developer portal: Weezdraw adds the SDK and a bridge to the page when it is served, and the bridge reports the score for you. The game's files are not modified.
{
"version": 1,
"readiness": { "expression": "typeof s_oGame !== 'undefined'" },
"score": { "method": "function_hook", "functionPath": "s_oGame.addScore",
"argumentIndex": 0, "accumulate": true },
"gameOver": { "method": "function_called", "functionPath": "s_oGame.gameOver" },
"menuSkip": { "method": "none" },
"hud": { "type": "none" }
}- score.method:
global_variable(a path likegame.score),function_hook(an argument of a game function, optionally accumulated),dom_element(a number shown on screen),custom_event(a DOM event's detail). - gameOver.method:
global_variable(becomes true),function_called(with optionalcallCountorargumentMatch),dom_appears(an end screen appears), oranchor: a unique piece of the game's code where the game ends (in the entry page or in one of its .js files), plus the expression giving the score there (scoreExpr). - finalScoreSource:
last_update(default),function_argumentorelapsed_time(withtimer, for races; set"metric": "time"). - menuSkip: click a Play button (
click_element) or call the game's start function (function_call, optionally replacing its menu withinterceptPath). - readiness.expression: when the game is ready; the bridge then starts the game on the server (same as
WZ.gameplayStart()). hud:timershows a clock over the game.
Check it in the preview: the SDK inspector shows what the bridge reports.
8. Testing your game
On your computer: open your index.html. The SDK runs in standalone mode, every call works and resolves at once. Add ?seed=42 to the URL to replay the same random sequence.
In 30 seconds, in your browser: open your index.html (add ?retries=3 to the URL to simulate three allowed games), paste this in the console, and play to the end:
addEventListener("message", (e) =>
e.data?.type?.startsWith("weezdraw:") && console.log("WZ →", e.data));Check that: the result matches your game-over screen (for times, metadata.display shows the right seconds); nothing is sent when a life is lost; with ?retries=N the final weezdraw:gameOver comes only after the last game, once, with the best result.
On Weezdraw: after uploading, open Preview from your dashboard. It runs your game in sandbox mode with an SDK inspector listing every call your game makes, so you can check that gameplayStart, progress and the final result are sent at the right moments. Nothing is recorded in sandbox mode.
9. API reference
| WZ.init(options?) | Promise<context>. Call once at startup. |
| WZ.loading(percent) | Loading progress, 0–100. |
| WZ.ready() | The game is loaded. |
| WZ.gameplayStart() | Promise<{ allowed, attempt, seed }>. The player starts a game. |
| WZ.progress(score) | Live score; also a heartbeat for the server. |
| WZ.points(score, meta?) | Promise. Final result, higher is better. |
| WZ.time(ms, meta?) | Promise. Final result, lower is better. |
| WZ.composite(score, parts?, meta?) | Promise. Final result, higher is better. |
| WZ.gameOver(score) | Alias of WZ.points. |
| WZ.finish() | Ends the session (endless games). |
| WZ.random() / randomInt(a, b) / randomRange(a, b) | Fair random numbers. |
| WZ.stream(name) | An independent fair sequence for one part of the game. |
| WZ.on(event, fn) | pause, resume, mute, unmute, start. |
| WZ.context / WZ.seed / WZ.version | Current context, competition seed, SDK version. |
Games written for SDK 1 (the original Weezdraw integration guide: WZ.points, WZ.time, WZ.composite, WZ.gameOver, WZ.finish, ?game= / ?retries=, one weezdraw:gameOver with the best of N) work unchanged with SDK 2. Adding WZ.gameplayStart() and WZ.random() brings server-side counting and fair randomness. Games using the earlier WeezdrawGame SDK (init, reportProgress, gameOver, onPause, onResume) and its URL parameters (gameSlug, gameSeed) work too.
10. Submitting your game
- Create a developer account.
- Build your game as a ZIP with an
index.html(at the root or in one folder) and a poster image. - Choose Submit a game in the developer portal. We check the ZIP and tell you whether the SDK and a result call were found.
- Open the preview and check the inspector.
- Weezdraw reviews the game. Once approved it goes live; you then see its plays and your earnings.