NUGANUGA Web SDK
Twoja gra działa w izolowanej ramce iframe na https://play.nuganuga.com. SDK to jedyny kanał do platformy — nigdy sam nie implementujesz logowania, rankingów, udostępniania, reklam ani analityki.
1. Wczytaj SDK
Zawsze z dokładnie tej ścieżki bezwzględnej. Platforma go serwuje i wersjonuje.
<script src="/sdk/nuga-sdk.js"></script>
<script src="./game.js"></script>2. Cztery wywołania
const ctx = await Nuga.ready(); // poczekaj na platformę
await Nuga.game.start(); // gdy gracz naprawdę zaczyna partię
await Nuga.score.submit({ score }); // dokładnie jeden wynik liczbowy na partię
await Nuga.game.finish(); // platforma rysuje ekran wynikuNie rysuj własnego ekranu wyniku, przycisku powtórki, przycisku udostępniania ani tablicy wyników — platforma narysuje je po finish(), identycznie dla każdej gry.
3. Cała reszta
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. Manifest
nuga.json w katalogu głównym twojej paczki:
{
"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개의 타겟을 빠르게 클릭하세요." }
}
}Typy rankingu: HIGH_SCORE, LOW_SCORE, LOW_TIME, HIGH_TIME, CUSTOM. Kategorie: REACTION, TIMING, ACCURACY, MEMORY, PUZZLE, LUCK, ARCADE.
5. Zasady piaskownicy
Walidacja statyczna odrzuci paczkę łamiącą którąkolwiek z nich, zanim trafi ona do gracza:
- Żadnych zewnętrznych adresów URL — bez CDN, czcionek webowych i zdalnych obrazów. Spakuj wszystko.
- Żadnego
eval,new Function,document.writeanidocument.cookie. - Żadnej własnej sieci:
fetchna adres bezwzględny,XMLHttpRequest,WebSocketi service workery są blokowane zarówno przez CSP, jak i przez walidację. - Żadnej nawigacji najwyższego poziomu i żadnych wyskakujących okien.
- Paczka poniżej 5 MB; mikrogry najlepiej poniżej 1 MB.
- Przynajmniej jedno wywołanie
Nuga.score.submit()— gra, która nie daje wyniku, nie wejdzie do rankingu. - Powłoka platformy jest stała: index.html, arkusz stylów powłoki i harness w game.js muszą pozostać bez zmian. Tylko ciało run() i style #field należą do Ciebie.
6. Wyniki są weryfikowane
Każda partia dostaje sesję po stronie serwera. Twoja gra nigdy nie widzi tokenu sesji — trzyma go powłoka platformy i wysyła wynik za ciebie — a serwer porównuje wynik z rzeczywistym czasem trwania i granicami z manifestu, zanim trafi on do rankingu.
Możesz zrobić to lepiej. Czerp losowość z ziarna wydanego przez serwer i zapisuj, co naprawdę się wydarzyło: serwer przeliczy partię z twoich zdarzeń, zamiast wierzyć liczbie. Wynik, którego powtórka nie potwierdza, zostaje odrzucony od razu.
const rng = Nuga.random(); // ziarno od serwera — powtarzalne, w odróżnieniu od Math.random()
const target = rng.int(0, 8);
Nuga.replay.record('hit', 172); // jedno zdarzenie istotne dla wyniku, do 400 na partięZadeklaruj mechanikę w nuga.json, aby to włączyć. Bez tego gra nadal wchodzi do rankingu, ale tylko z kontrolą czasu i granic.
"verification": { "kind": "REPLAY_V1", "mechanic": "REACTION",
"params": { "rounds": 5 } }7. Opublikuj
Spakuj katalog główny paczki (nie folder) i wgraj go w konsoli twórcy. Walidacja statyczna, budowanie oraz zestawy runtime, responsywności, rozgrywki i bezpieczeństwa uruchamiają się automatycznie; publikacja odblokowuje się, gdy przejdą.