NUGANUGA Web-SDK
Dit spil kører i en sandkasse-iframe på https://play.nuganuga.com. SDK’en er den eneste kanal til platformen — du bygger aldrig selv login, ranglister, deling, annoncer eller analyse.
1. Indlæs SDK’en
Altid fra præcis denne absolutte sti. Platformen leverer og versionerer den.
<script src="/sdk/nuga-sdk.js"></script>
<script src="./game.js"></script>2. De fire kald
const ctx = await Nuga.ready(); // vent på platformen
await Nuga.game.start(); // når spilleren faktisk starter en runde
await Nuga.score.submit({ score }); // præcis én numerisk score pr. runde
await Nuga.game.finish(); // platformen tegner resultatskærmenTegn ikke din egen resultatskærm, gentag-knap, del-knap eller rangliste — platformen tegner dem efter finish(), ens for hvert spil.
3. Alt det andet
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 roden af dit bundt:
{
"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개의 타겟을 빠르게 클릭하세요." }
}
}Ranglistetyper: HIGH_SCORE, LOW_SCORE, LOW_TIME, HIGH_TIME, CUSTOM. Kategorier: REACTION, TIMING, ACCURACY, MEMORY, PUZZLE, LUCK, ARCADE.
5. Sandkassens regler
Den statiske validering afviser et bundt, der bryder én af dem, før det når en spiller:
- Ingen eksterne URL’er — ingen CDN, webfont eller fjernbillede. Pak alt med selv.
- Ingen
eval,new Function,document.writeellerdocument.cookie. - Intet eget netværk:
fetchmod en absolut URL,XMLHttpRequest,WebSocketog service workers blokeres både af CSP og af valideringen. - Ingen navigation på topniveau og ingen pop op-vinduer.
- Bundtet under 5 MB; mikrospil bør holde sig under 1 MB.
- Mindst ét
Nuga.score.submit()-kald — et spil uden score kan ikke rangeres. - Platformskallen er fast: index.html, skallens stylesheet og selen i game.js skal være uændrede. Kun run()-kroppen og #field-stilarter er dine.
6. Scorer bliver verificeret
Hver runde får en session på serveren. Dit spil ser aldrig sessionstokenet — platformskallen holder det og indsender for dig — og serveren holder scoren op mod rundens faktiske varighed og manifestets grænser, før den kommer på en rangliste.
Du kan gøre det bedre. Træk tilfældigheden fra det frø, serveren udsteder, og registrér, hvad der faktisk skete: så genberegner serveren runden ud fra dine hændelser i stedet for at tro på tallet. En score, dit replay ikke understøtter, bliver afvist direkte.
const rng = Nuga.random(); // frø fra serveren — reproducerbart, modsat Math.random()
const target = rng.int(0, 8);
Nuga.replay.record('hit', 172); // ét scorerelevant udfald, op til 400 pr. rundeErklær mekanikken i nuga.json for at slå det til. Uden den bliver dit spil stadig rangeret — bare på varigheds- og grænsetjek.
"verification": { "kind": "REPLAY_V1", "mechanic": "REACTION",
"params": { "rounds": 5 } }7. Udgiv det
Zip bundtets rod (ikke mappen), og upload den i skaberkonsollen. Statisk validering, build samt runtime-, responsiv-, gameplay- og sikkerhedstest kører automatisk; udgivelse låses op, når de består.