NUGANUGA Web-SDK
Spillet ditt kjører i en sandkasse-iframe på https://play.nuganuga.com. SDK-en er den eneste kanalen til plattformen — du lager aldri egen innlogging, rangering, deling, annonsering eller analyse.
1. Last inn SDK-en
Alltid fra akkurat denne absolutte stien. Plattformen leverer og versjonerer den.
<script src="/sdk/nuga-sdk.js"></script>
<script src="./game.js"></script>2. De fire kallene
const ctx = await Nuga.ready(); // vent på plattformen
await Nuga.game.start(); // når spilleren faktisk starter en runde
await Nuga.score.submit({ score }); // nøyaktig én numerisk poengsum per runde
await Nuga.game.finish(); // plattformen tegner resultatskjermenIkke tegn din egen resultatskjerm, omspillsknapp, delingsknapp eller ledertavle — plattformen tegner dem etter finish(), likt for hvert spill.
3. Alt det andre
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. Manifestet
nuga.json i roten av pakken din:
{
"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개의 타겟을 빠르게 클릭하세요." }
}
}Rangeringstyper: HIGH_SCORE, LOW_SCORE, LOW_TIME, HIGH_TIME, CUSTOM. Kategorier: REACTION, TIMING, ACCURACY, MEMORY, PUZZLE, LUCK, ARCADE.
5. Sandkasseregler
Den statiske valideringen avviser en pakke som bryter én av dem, før den når en spiller:
- Ingen eksterne URL-er — ingen CDN, nettfont eller ekstern bildefil. Pakk alt selv.
- Ingen
eval,new Function,document.writeellerdocument.cookie. - Ingen egen nettverkstrafikk:
fetchmot en absolutt URL,XMLHttpRequest,WebSocketog service workers blokkeres både av CSP og av valideringen. - Ingen navigasjon på toppnivå og ingen popup-vinduer.
- Pakken under 5 MB; mikrospill bør holde seg under 1 MB.
- Minst ett
Nuga.score.submit()-kall — et spill uten poengsum kan ikke rangeres. - Plattformskallet er fast: index.html, skallets stilark og selen i game.js må være uendret. Bare run()-kroppen og #field-stiler er dine.
6. Poengsummer verifiseres
Hver runde får en økt på serversiden. Spillet ditt ser aldri økttokenet — plattformskallet holder det og sender inn på dine vegne — og serveren sjekker poengsummen mot faktisk varighet og grensene i manifestet før den havner på en ledertavle.
Du kan gjøre det bedre. Hent tilfeldigheten fra frøet serveren gir ut, og registrer hva som faktisk skjedde: da regner serveren ut runden på nytt fra hendelsene dine i stedet for å stole på tallet. En poengsum reprisen din ikke støtter, blir avvist direkte.
const rng = Nuga.random(); // frø fra serveren — reproduserbart, i motsetning til Math.random()
const target = rng.int(0, 8);
Nuga.replay.record('hit', 172); // ett poengrelevant utfall, opptil 400 per rundeDeklarer mekanikken i nuga.json for å slå det på. Uten den blir spillet fortsatt rangert, bare på varighets- og grensesjekker.
"verification": { "kind": "REPLAY_V1", "mechanic": "REACTION",
"params": { "rounds": 5 } }7. Publiser
Zip roten av pakken (ikke mappen) og last den opp i skaperkonsollen. Statisk validering, bygging og testsettene for runtime, responsivitet, spillbarhet og sikkerhet kjøres automatisk; publisering låses opp når de består.