NUGANUGA Web SDK
Το παιχνίδι σου τρέχει σε απομονωμένο iframe στο https://play.nuganuga.com. Το 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. Κανόνες απομόνωσης
Ο στατικός έλεγχος απορρίπτει πακέτο που παραβιάζει οποιονδήποτε από αυτούς, πριν φτάσει σε παίκτη:
- Καμία εξωτερική διεύθυνση — ούτε CDN, ούτε γραμματοσειρά ιστού, ούτε απομακρυσμένη εικόνα. Πακετάρισέ τα όλα.
- Ούτε
eval, ούτεnew Function, ούτεdocument.writeήdocument.cookie. - Κανένα δικό σου δίκτυο:
fetchσε απόλυτη διεύθυνση,XMLHttpRequest,WebSocketκαι service worker μπλοκάρονται τόσο από την CSP όσο και από τον έλεγχο. - Καμία πλοήγηση ανώτατου επιπέδου και κανένα αναδυόμενο παράθυρο.
- Πακέτο κάτω από 5 MB· τα μικροπαιχνίδια καλό είναι να μένουν κάτω από 1 MB.
- Τουλάχιστον μία κλήση
Nuga.score.submit()— παιχνίδι που δεν παράγει σκορ δεν μπορεί να μπει σε κατάταξη. - Το κέλυφος της πλατφόρμας είναι σταθερό: το index.html, το φύλλο στυλ του κελύφους και το harness στο 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. Δημοσίευσέ το
Συμπίεσε τη ρίζα του πακέτου (όχι τον φάκελο) και ανέβασέ την στην κονσόλα δημιουργού. Ο στατικός έλεγχος, το χτίσιμο και οι δοκιμές runtime, απόκρισης, παικτικότητας και ασφάλειας τρέχουν αυτόματα· η δημοσίευση ξεκλειδώνει μόλις περάσουν.