NUGANUGA Web SDK
Jocul tău rulează într-un iframe izolat pe https://play.nuganuga.com. SDK-ul este singurul canal către platformă — nu implementezi niciodată singur autentificarea, clasamentele, distribuirea, reclamele sau analiza.
1. Încarcă SDK-ul
Întotdeauna exact de la această cale absolută. Platforma îl servește și îl versionează.
<script src="/sdk/nuga-sdk.js"></script>
<script src="./game.js"></script>2. Cele patru apeluri
const ctx = await Nuga.ready(); // așteaptă platforma
await Nuga.game.start(); // când jucătorul chiar începe o rundă
await Nuga.score.submit({ score }); // exact un scor numeric pe rundă
await Nuga.game.finish(); // platforma desenează ecranul de rezultatNu desena propriul ecran de rezultat, buton de reluare, buton de distribuire sau clasament — platforma le afișează după finish(), identic pentru fiecare joc.
3. Tot restul
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. Manifestul
nuga.json în rădăcina pachetului tău:
{
"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개의 타겟을 빠르게 클릭하세요." }
}
}Tipuri de clasament: HIGH_SCORE, LOW_SCORE, LOW_TIME, HIGH_TIME, CUSTOM. Categorii: REACTION, TIMING, ACCURACY, MEMORY, PUZZLE, LUCK, ARCADE.
5. Regulile mediului izolat
Validarea statică respinge orice pachet care încalcă una dintre ele, înainte să ajungă la un jucător:
- Fără URL-uri externe — fără CDN, font web sau imagine de la distanță. Împachetează tot.
- Fără
eval,new Function,document.writesaudocument.cookie. - Fără rețea proprie:
fetchcătre un URL absolut,XMLHttpRequest,WebSocketși service worker sunt blocate atât de CSP, cât și de validare. - Fără navigare la nivelul de sus și fără ferestre pop-up.
- Pachet sub 5 MB; microjocurile ar trebui să rămână sub 1 MB.
- Cel puțin un apel
Nuga.score.submit()— un joc care nu produce scor nu poate intra în clasament. - Învelișul platformei este fix: index.html, foaia de stil a învelișului și harness-ul din game.js trebuie să rămână neschimbate. Doar corpul run() și stilurile #field sunt ale tale.
6. Scorurile sunt verificate
Fiecare rundă primește o sesiune pe server. Jocul tău nu vede niciodată tokenul de sesiune — îl păstrează învelișul platformei și trimite în locul tău — iar serverul compară scorul cu durata reală și cu limitele declarate în manifest înainte să intre într-un clasament.
Poți face mai bine. Ia aleatoriul din sămânța emisă de server și înregistrează ce s-a întâmplat cu adevărat: serverul va recalcula runda din evenimentele tale în loc să creadă numărul. Un scor pe care înregistrarea nu îl susține este respins direct.
const rng = Nuga.random(); // sămânță de la server — reproductibil, spre deosebire de Math.random()
const target = rng.int(0, 8);
Nuga.replay.record('hit', 172); // un rezultat relevant pentru scor, până la 400 pe rundăDeclară mecanica în nuga.json ca să activezi asta. Fără ea, jocul tău intră totuși în clasament, doar cu verificări de durată și limite.
"verification": { "kind": "REPLAY_V1", "mechanic": "REACTION",
"params": { "rounds": 5 } }7. Publică-l
Arhivează rădăcina pachetului (nu folderul) și încarc-o în consola creatorului. Validarea statică, build-ul și seturile de teste runtime, responsivitate, gameplay și securitate rulează automat; publicarea se deblochează când trec toate.