NUGANUGA Webb-SDK
Ditt spel körs i en sandlådad iframe på https://play.nuganuga.com. SDK:n är enda kanalen till plattformen — du bygger aldrig egen inloggning, rankning, delning, annonsering eller analys.
1. Ladda SDK:n
Alltid från exakt den här absoluta sökvägen. Plattformen serverar och versionerar den.
<script src="/sdk/nuga-sdk.js"></script>
<script src="./game.js"></script>2. De fyra anropen
const ctx = await Nuga.ready(); // vänta på plattformen
await Nuga.game.start(); // när spelaren verkligen startar en omgång
await Nuga.score.submit({ score }); // exakt en numerisk poäng per omgång
await Nuga.game.finish(); // plattformen ritar resultatskärmenRita ingen egen resultatskärm, omspelsknapp, delningsknapp eller topplista — plattformen ritar dem efter finish(), likadant för varje spel.
3. Allt annat
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 ditt paket:
{
"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개의 타겟을 빠르게 클릭하세요." }
}
}Rankningstyper: HIGH_SCORE, LOW_SCORE, LOW_TIME, HIGH_TIME, CUSTOM. Kategorier: REACTION, TIMING, ACCURACY, MEMORY, PUZZLE, LUCK, ARCADE.
5. Sandlådans regler
Den statiska valideringen avvisar ett paket som bryter mot någon av dem, innan det når en spelare:
- Inga externa URL:er — inget CDN, inget webbtypsnitt, ingen fjärrbild. Paketera allt själv.
- Inget
eval,new Function,document.writeellerdocument.cookie. - Inget eget nätverk:
fetchmot en absolut URL,XMLHttpRequest,WebSocketoch service workers blockeras både av CSP och av valideringen. - Ingen navigering på toppnivå och inga popup-fönster.
- Paketet under 5 MB; mikrospel bör hålla sig under 1 MB.
- Minst ett
Nuga.score.submit()-anrop — ett spel utan poäng kan inte rankas. - Plattformsskalet är fast: index.html, skalets stilmall och selen i game.js måste vara oförändrade. Bara run()-kroppen och #field-stilar är dina.
6. Poängen verifieras
Varje omgång får en session på serversidan. Ditt spel ser aldrig sessionstoken — plattformsskalet håller den och skickar in åt dig — och servern stämmer av poängen mot den faktiska speltiden och gränserna i manifestet innan den hamnar på en topplista.
Du kan göra bättre. Hämta slumpen ur det frö servern delar ut och registrera vad som faktiskt hände, så räknar servern om omgången från dina händelser i stället för att lita på siffran. En poäng som ditt replay inte stöder avvisas direkt.
const rng = Nuga.random(); // frö från servern — reproducerbart, till skillnad från Math.random()
const target = rng.int(0, 8);
Nuga.replay.record('hit', 172); // ett poängrelevant utfall, upp till 400 per omgångDeklarera mekaniken i nuga.json för att slå på det. Utan den rankas spelet ändå, men bara på tids- och gränskontroller.
"verification": { "kind": "REPLAY_V1", "mechanic": "REACTION",
"params": { "rounds": 5 } }7. Släpp det
Zippa paketets rot (inte mappen) och ladda upp den i skaparkonsolen. Statisk validering, bygge och sviterna för runtime, responsivitet, spelbarhet och säkerhet körs automatiskt; publicering låses upp när de är godkända.