NUGANUGA 웹 SDK
게임은 https://play.nuganuga.com의 샌드박스 iframe 안에서 실행됩니다. SDK가 플랫폼과 연결되는 유일한 통로이며, 인증·랭킹·공유·광고·분석을 직접 구현할 필요가 없습니다.
1. SDK 불러오기
반드시 이 절대 경로를 사용하세요. 플랫폼이 배포와 버전 관리를 담당합니다.
<script src="/sdk/nuga-sdk.js"></script>
<script src="./game.js"></script>2. 네 번의 호출
const ctx = await Nuga.ready(); // 플랫폼 준비 대기
await Nuga.game.start(); // 플레이어가 실제로 플레이를 시작할 때
await Nuga.score.submit({ score }); // 한 판당 정확히 하나의 숫자 점수
await Nuga.game.finish(); // 플랫폼이 결과 화면을 그립니다결과 화면, 다시하기 버튼, 공유 버튼, 리더보드를 직접 그리지 마세요. finish() 이후 플랫폼이 모든 게임에 동일하게 그려줍니다.
3. 그 밖의 기능
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. 매니페스트
번들 루트에 두는 nuga.json 파일:
{
"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개의 타겟을 빠르게 클릭하세요." }
}
}랭킹 타입: HIGH_SCORE, LOW_SCORE, LOW_TIME, HIGH_TIME, CUSTOM. 카테고리: REACTION, TIMING, ACCURACY, MEMORY, PUZZLE, LUCK, ARCADE.
5. 샌드박스 규칙
아래를 위반한 번들은 플레이어에게 도달하기 전에 정적 검증에서 거부됩니다:
- 외부 URL 금지 — CDN, 웹폰트, 원격 이미지 모두 불가. 전부 번들에 포함하세요.
eval,new Function,document.write,document.cookie사용 금지.- 자체 네트워크 통신 금지: 절대 URL
fetch,XMLHttpRequest,WebSocket, 서비스 워커는 정적 검증과 CSP 양쪽에서 차단됩니다. - 최상위 창 이동과 팝업 금지.
- 번들 5MB 이하 — 마이크로게임은 1MB 이하를 권장합니다.
Nuga.score.submit()호출 최소 1회 — 점수를 만들 수 없는 게임은 랭킹에 오를 수 없습니다.- 플랫폼 셸은 고정입니다. index.html, 셸 스타일시트, game.js의 하네스는 그대로여야 하며, run() 본문과 #field 스타일만 바꿀 수 있습니다.
6. 점수는 서버에서 검증됩니다
모든 플레이에는 서버가 발급한 세션이 있습니다. 게임 코드는 세션 토큰을 볼 수 없으며, 플랫폼 셸이 대신 보관하고 제출합니다. 서버는 실제 경과 시간과 매니페스트에 선언된 범위를 대조한 뒤에야 랭킹에 반영합니다.
여기서 한 단계 더 나아갈 수 있습니다. 서버가 발급한 시드로 난수를 만들고 실제로 일어난 일을 기록하면, 서버가 보고된 숫자를 믿는 대신 그 기록으로 점수를 다시 계산합니다. 기록이 뒷받침하지 못하는 점수는 그대로 거부됩니다.
const rng = Nuga.random(); // 서버 시드 기반 — Math.random()과 달리 재현 가능
const target = rng.int(0, 8);
Nuga.replay.record('hit', 172); // 점수와 관련된 결과 하나, 한 판에 최대 400개nuga.json에 메커닉을 선언하면 켜집니다. 선언하지 않아도 랭킹에는 오르지만, 시간과 범위 검사만 적용됩니다.
"verification": { "kind": "REPLAY_V1", "mechanic": "REACTION",
"params": { "rounds": 5 } }7. 배포하기
폴더가 아니라 번들 루트를 압축해 크리에이터 콘솔에 업로드하세요. 정적 검증, 빌드, 런타임, 반응형, 게임플레이, 보안 테스트가 자동으로 실행되고 모두 통과하면 공개가 열립니다.