← Arcade

PG SDK

Leaderboards and cloud saves for any game in the Arcade — Codpig games, Godot, Unity, Construct, plain JavaScript. Nothing to install: the PG object is already inside your game when it runs on PiGenerate. Players log in with their PiGenerate account; your game never sees their login.

Outside PiGenerate (on your own computer) PG does not exist, so guard calls: if (window.PG) …. Every call returns a Promise.

Scores

// after the game ends — the player's best is kept, a worse result does not overwrite it
const r = await PG.submitScore('main', 1200);
// r = { best: 1200, improved: true, rank: 3, order: 'desc' }

// lower is better (a race time, for example): the first call decides how the board is sorted
await PG.submitScore('time', 41.7, { order: 'asc' });

const t = await PG.getScores('main', { limit: 10 });
// t = { total, order, rows: [{ rank, name, score, user_id }], me: { rank, score } | null }

A leaderboard panel appears under the game on its page automatically once the first score is in. Up to 10 boards per game, board names up to 32 characters. The author can reset a board from that panel.

Saves

await PG.save({ level: 5, coins: 120, items: ['sword'] });   // slot 'main'
const data = await PG.load();                                 // object, or null when empty
await PG.save(state, 'slot2');                                // up to 5 slots per player, 256 KB each

Saves follow the player across devices.

Player

const p = await PG.player();   // { loggedIn: true, name: 'katedev' }

If the player is not logged in, submitScore, save and load fail with error.code === 'login' and the page shows a “Log in” bar under the game. getScores works for everyone.

Godot 4 (Web export)

func submit_score(score: int) -> void:
    if OS.has_feature("web"):
        JavaScriptBridge.eval("window.PG && PG.submitScore('main', %d)" % score)

func save_progress(json_text: String) -> void:
    if OS.has_feature("web"):
        JavaScriptBridge.eval("window.PG && PG.save(JSON.parse('%s'))" % json_text.replace("\\", "\\\\").replace("'", "\\'"))

Unity WebGL

Create Assets/Plugins/PG.jslib:

mergeInto(LibraryManager.library, {
  PG_SubmitScore: function (board, score) { if (window.PG) PG.submitScore(UTF8ToString(board), score); }
});

and in C#:

[System.Runtime.InteropServices.DllImport("__Internal")] static extern void PG_SubmitScore(string board, double score);
// PG_SubmitScore("main", 1200);

Multiplayer

Real-time rooms for 2–16 players. The server relays messages between the players of a room; nothing is stored. Guests can play too.

// quick match (a public room with free seats), or pass any code to play with friends: PG.mp.join('my-room')
const room = await PG.mp.join('auto', { max: 4 });
room.me        // your player id      room.players  // [{id, nick, user}]
room.host      // id of the host (the first player; passes on when they leave) — let the host run the game logic
room.code      // the room code — show it so friends can join

room.on('join',  p => addPlayer(p.id, p.nick));
room.on('leave', p => removePlayer(p.id));
room.on('host',  id => { if (id === room.me) becomeHost(); });
room.on('msg',  (data, from) => applyUpdate(from, data));

room.send({ x, y, angle });          // to everybody else in the room
room.send({ hit: 10 }, playerId);    // to one player
room.leave();

Tips. Send state 10–20 times a second, not every frame. Let the host decide important things (score, who won). Rooms disappear when the last player leaves.

Godot 4 / Unity. Call the same API from JavaScript: Godot — JavaScriptBridge.eval("PG.mp.join('auto').then(r => window.room = r)") and poll a small JS queue; Unity — a .jslib plugin that calls PG.mp.join / room.send and forwards room.on('msg', …) to SendMessage.

Limits

WhatLimit
Score valuesany number up to ±1 000 000 000 000
Rateone score and one save per player per second or so
Multiplayer16 KB per message, 30 messages a second per player, 2–16 players a room
Cheatingscores come from the game running in the player's browser, so a determined player can fake them — the author can reset a board.