SDK Web di NUGANUGA
Il tuo gioco gira in un iframe in sandbox su https://play.nuganuga.com. L’SDK è l’unico canale verso la piattaforma — non implementi mai da solo autenticazione, classifiche, condivisione, pubblicità o analisi.
1. Carica l’SDK
Sempre da questo percorso assoluto esatto. La piattaforma lo serve e ne gestisce le versioni.
<script src="/sdk/nuga-sdk.js"></script>
<script src="./game.js"></script>2. Le quattro chiamate
const ctx = await Nuga.ready(); // aspetta la piattaforma
await Nuga.game.start(); // quando il giocatore inizia davvero una partita
await Nuga.score.submit({ score }); // esattamente un punteggio numerico per partita
await Nuga.game.finish(); // la piattaforma disegna la schermata dei risultatiNon disegnare una tua schermata dei risultati, un pulsante riprova, un pulsante condividi o una classifica — la piattaforma li mostra dopo finish(), identici per ogni gioco.
3. Tutto il resto
Nuga.game.getContext();
Nuga.player.get();
Nuga.challenge.get();
Nuga.storage.get(key);
Nuga.storage.set(key, value);
Nuga.audio.setMuted(true);
Nuga.locale.get(); // 'en' | 'ko' | ...
Nuga.event.track('level_up', { level: 3 });
Nuga.on('pause', () => pauseLoop());4. Il manifest
nuga.json nella radice del tuo bundle:
{
"schemaVersion": 1,
"name": "Reaction Hunter",
"slug": "reaction-hunter",
"description": "Click 10 targets as fast as possible.",
"rule": "Tap every target as fast as you can.",
"category": "REACTION",
"orientation": "PORTRAIT",
"duration": { "min": 5, "max": 30 },
"input": ["POINTER", "TOUCH"],
"ranking": { "type": "LOW_TIME", "unit": "ms" },
"entry": "index.html",
"locales": {
"ko": { "name": "리액션 헌터", "description": "10개의 타겟을 빠르게 클릭하세요." }
}
}Tipi di classifica: HIGH_SCORE, LOW_SCORE, LOW_TIME, HIGH_TIME, CUSTOM. Categorie: REACTION, TIMING, ACCURACY, MEMORY, PUZZLE, LUCK, ARCADE.
5. Regole della sandbox
La validazione statica rifiuta un bundle che viola una di queste, prima ancora che arrivi a un giocatore:
- Nessun URL esterno — niente CDN, niente web font, niente immagini remote. Includi tutto nel bundle.
- Niente
eval,new Function,document.writeodocument.cookie. - Niente rete tua:
fetchverso un URL assoluto,XMLHttpRequest,WebSockete i service worker sono bloccati sia dalla CSP sia dalla validazione. - Niente navigazione di primo livello e niente popup.
- Bundle sotto i 5 MB; i microgiochi dovrebbero restare sotto 1 MB.
- Almeno una chiamata a
Nuga.score.submit()— un gioco che non produce un punteggio non può entrare in classifica. - La shell della piattaforma è fissa: index.html, il foglio di stile della shell e l’harness in game.js devono restare invariati. Solo il corpo di run() e gli stili di #field sono tuoi.
6. I punteggi vengono verificati
Ogni partita riceve una sessione lato server. Il tuo gioco non vede mai il token di sessione — lo tiene il guscio della piattaforma, che invia per tuo conto — e il server confronta il punteggio con la durata reale e con i limiti dichiarati nel manifest prima che entri in una classifica.
Puoi fare di meglio. Ricava la casualità dal seed emesso dal server e registra ciò che è realmente accaduto: il server ricalcolerà la partita dai tuoi eventi invece di fidarsi del numero. Un punteggio che il tuo replay non sostiene viene rifiutato senza appello.
const rng = Nuga.random(); // seed dal server — riproducibile, a differenza di Math.random()
const target = rng.int(0, 8);
Nuga.replay.record('hit', 172); // un esito rilevante per il punteggio, fino a 400 per partitaDichiara la meccanica in nuga.json per attivarlo. Senza, il tuo gioco resta in classifica, ma solo con i controlli su durata e limiti.
"verification": { "kind": "REPLAY_V1", "mechanic": "REACTION",
"params": { "rounds": 5 } }7. Pubblicalo
Comprimi la radice del bundle (non la cartella) e caricala nella console creator. Validazione statica, build e le suite runtime, responsive, gameplay e sicurezza girano in automatico; la pubblicazione si sblocca quando passano.