- klyo games
- Dla twórców
- Zestaw dla gry
Dokumentacja
Zestaw klyo dla gry HTML5
Jeden plik dołączony do gry i twoja gra umie rozmawiać ze stroną, na której stoi: wysyła wynik na tablicę, zapisuje postęp gracza na serwerze, prosi o przerwę reklamową i pozwala nagrać klip. Gra nie dostaje dostępu ani do strony, ani do reklam, ani do serwera. Prosi, a strona decyduje.
Jak dołączyć zestaw do gry
Jedna linia w pliku index.html, przed twoim skryptem. Zestaw działa też wtedy, gdy ktoś otworzy grę poza katalogiem: wywołania nie wywalają się, tylko odpowiadają natychmiast. Nazwy są angielskie (twórcy są z całego świata); polskie nazwy z wcześniejszych wersji (klyo.gotowa, klyo.wynik, klyo.postep, klyo.tablica, klyo.zapis, klyo.przerwa, klyo.nagroda, klyo.pelnyEkran, klyo.obraz) działają dalej, bo to te same funkcje.
<script src="https://games.klyo.pl/sdk/klyo-gry-sdk.js"></script>
Jak zgłosić, że gra jest gotowa do grania
Wywołaj to, gdy gra się wczytała i da się w nią grać. Strona chowa wtedy zasłonę ładowania i przestaje pokazywać kręcące się kółko.
klyo.ready();
Jak wysłać wynik gracza na tablicę
Po każdej skończonej partii. Wynik trafia na tablicę na serwerze i do rekordów gracza, także wtedy, gdy zagra na drugim urządzeniu, jeśli ma konto. Odpowiedź niesie wszystko na ekran końca: pozycję dziś ze skokiem, w tygodniu, od zawsze i gracza tuż nad.
klyo.score(1200, (o) => {
// o.todayRank, o.previousTodayRank (skok),
// o.weekRank, o.allTimeRank,
// o.above = { name, score } → „320 do OpenGamers”
pokazEkranKonca(o);
});
Jak dać graczowi cel w trakcie partii
Wołaj przy każdej zmianie wyniku, a zestaw sam trzyma tempo (do 4 razy na sekundę). Strona pokazuje pod grą żeton „#14 · 320 do OpenGamers”, a przy mijaniu „↑ #13, wyprzedzasz…”. Bez tego wywołania żetonu nie ma; nic nie idzie do sieci, to rozmowa ze stroną.
klyo.progress(punkty);
Jak pokazać dwadzieścia najlepszych wyników
Trzy okresy: day, week, all. Odpowiedź zawiera podpisy graczy, te same, które widać w społeczności.
klyo.leaderboard.get("day", (t) => {
pokazTablice(t.entries);
});
Drużyny, mapy i zaproszenie jednym linkiem
Drużyny i mapy podajesz w lobby, a trzyma je pokój na serwerze: lobby portalu pokazuje kolumny drużyn z liczbą miejsc (gracz wybiera, pełna drużyna odmawia) i kafelki map (wybiera gospodarz). Link zaproszenia prowadzi znajomego prosto do pokoju i do drużyny tego, kto go wysłał, więc gracie razem. Na komputerze wystarczy otworzyć link, na telefonie jedno dotknięcie karty zaproszenia. Szybki mecz dobiera po mapie i drużynie, a z dropIn wpuszcza od razu do trwającego meczu. Strony i mapę ustawiaj tylko z room().players[i].team i room().map, nigdy z lokalnego wyboru w menu gry: tak dwaj gracze, którzy wybrali atak, na pewno trafią do jednej drużyny.
klyo.online.onInvite(() => graOnline()); // gracz z linku
function graOnline() {
klyo.online.lobby({ players: 10, mode: "realtime", dropIn: true,
teams: [{ id: "atak", name: "Atak" }, { id: "obrona", name: "Obrona" }],
maps: [{ id: "port", name: "Port", image: "mapy/port.webp" }] }, (o) => {
if (!o.ok) return;
const ja = o.room.players.find((g) => g.who === o.room.me);
zacznijMecz(o.room.map, ja.team, o.room.players);
});
}
Jak serwer pilnuje zasad meczu
Zasady meczu wpisujesz do pliku klyo-rules.json w paczce: ile razy na sekundę wolno strzelić, ile naboi ma magazynek, co go odnawia i jak długo trwa przeładowanie, jak szybko porusza się postać i jakie są największe obrażenia. Plik czytamy przy wydaniu, więc gracz nie zmieni go w przeglądarce. Serwer meczów sprawdza każdą akcję, zanim zobaczą ją inni gracze, także na zapasowym połączeniu. Złamana zasada nie dochodzi do nikogo, a twoja gra dostaje onReject z powodem. Trafienia i punkty przyjmuj tylko z wiadomości z polem action.
klyo.online.act("shoot", { damage: 36, hit: cel });
klyo.online.pos(x, y, z);
klyo.online.onReject((r) => {
// r.reason: "burst-empty", "locked", "too-fast", "too-far"
poprawAmunicje(r);
});
// klyo-rules.json:
// { "online": { "actions": { "shoot": { "perSecond": 10, "burst": 30, "refill": "reload" },
// "reload": { "lockMs": 2500 } }, "position": { "maxSpeed": 7.5 } } }
Jak pokazać turniej tygodnia
Każda gra z zestawem ma turniej sama: od poniedziałku do niedzieli, bez nagród pieniężnych, podium dostaje XP (100, 60 i 30), gdy grało co najmniej trzech graczy. Do tabeli wchodzą tylko wyniki, które przeszły sprawdzenie uczciwości. Odpowiedź ma koniec edycji, 50 najlepszych, twoje miejsce i zwycięzców ostatnich tygodni.
klyo.tournament.get((t) => {
// t.endsAt, t.entries, t.me = { rank, score },
// t.winners = [{ edition, name, score }]
pokazTurniej(t);
});
Jak zapisać postęp gracza między urządzeniami
Do 64 KB na gracza i grę, na naszym serwerze, z kopią w przeglądarce. Wczytaj na starcie, zapisuj po ważnych zmianach: zapisy częstsze niż co 2 sekundy zestaw sam łączy w jeden i wysyła ostatni stan. Odpowiedź mówi, skąd są dane: z.cloud znaczy, że odpowiedział serwer klyo, a z.reason mówi, dlaczego dane są tylko z przeglądarki. Odpowiedź przychodzi zawsze, więc nie dokładaj własnego limitu czasu.
klyo.save.get((z) => {
if (z.ok && z.data) wczytajStan(z.data);
// z.cloud: odpowiedział serwer klyo
// z.reason: dlaczego tylko kopia z przeglądarki
});
klyo.save.set({ poziom: 4, zloto: 120 }, (o) => {
if (!o.cloud) pokazUwage(o.reason);
});
Jak zapisać postęp gracza w grze HTML5
Jak sprawdzić zapis w chmurze przed wydaniem gry
Wgraj paczkę w studiu i zagraj w oknie podglądu: zestaw odpowiada tam na każde wywołanie. Zapis idzie do chmury podglądu, którą widzisz tylko ty; gracze po wydaniu zaczynają od zera, a zapis znika razem z podglądem. Nowa wersja wydanej gry czyta w podglądzie twój zapis z gry, dopóki nie zapisze własnego, więc sprawdzisz, czy wczyta postęp graczy. Przerwa i reklama za nagrodę pokazują zaślepkę na 3 i 5 sekund, wynik i tablica pokazują wyniki z podglądu, a turniej, ligi i pokoje online odpowiadają od razu powodem podglad i sprawdzisz je na stronie gry po wydaniu. Kod QR otwiera grę na telefonie bez strony klyo: tam zapis zostaje w telefonie.
klyo.save.set({ test: 1 }, (o) => {
console.log(o.cloud, o.preview, o.updatedAt); // true, true, chwila zapisu na serwerze
});
// później albo po ponownym otwarciu podglądu:
klyo.save.get((z) => console.log(z.source, z.data)); // "chmura" { test: 1 }
Jak zapisać postęp gracza w grze HTML5
Jak zapisać postęp gry z Godota w przeglądarce
Godot 4 w eksporcie do przeglądarki woła zestaw przez JavaScriptBridge: get_interface("klyo") daje obiekt zestawu, a create_callback odbiera odpowiedź jako tablicę z jednym obiektem. Odwołanie trzymaj w zmiennej klasy, inaczej odpowiedź nie przyjdzie. Stan wysyłaj jako tekst JSON i czytaj go przez JSON.parse_string. Poza przeglądarką OS.has_feature("web") zwraca fałsz i gra zapisuje po swojemu.
var _klyo = JavaScriptBridge.get_interface("klyo") if OS.has_feature("web") else null
var _po_wczytaniu = JavaScriptBridge.create_callback(_wczytano)
var _po_zapisie = JavaScriptBridge.create_callback(_zapisano)
func wczytaj() -> void:
if _klyo: _klyo.save.get(_po_wczytaniu)
func _wczytano(args: Array) -> void:
var z = args[0]
if z.ok and z.data:
var stan = JSON.parse_string(z.data)
func zapisz(stan: Dictionary) -> void:
if _klyo: _klyo.save.set(JSON.stringify(stan), _po_zapisie)
func _zapisano(args: Array) -> void:
print(args[0].cloud, " ", args[0].reason)
Jak wstawić przerwę reklamową w dobrym miejscu
Ty wybierasz moment, nie my. Dobre miejsca to koniec poziomu i ekran po przegranej; złe to środek walki. Gra czeka na wywołanie zwrotne, zanim ruszy dalej.
klyo.adBreak("between-levels", () => {
wznowGre();
});
Jak dać reklamę za nagrodę
Gracz sam ją włącza przyciskiem: „obejrzyj i zgarnij bonus”. Nagrodę dajesz WYŁĄCZNIE wtedy, gdy odpowiedź ma ok równe prawda; fałsz znaczy, że reklamy nie było, nie dobiegła końca albo gracz ją zamknął.
przyciskBonus.onclick = () => {
klyo.rewardedAd((o) => {
if (o.ok) dajBonus(500);
else powiedz("Bonus następnym razem.");
});
};
Jak poprosić o pełny ekran
Przeglądarki wpuszczają na pełny ekran tylko w odpowiedzi na kliknięcie gracza, więc wywołaj to z obsługi kliknięcia, a nie po wczytaniu gry.
klyo.fullscreen();
Jak pozwolić graczowi nagrać klip z twojej gry
Jedna linia i gracz ma na stronie działający przycisk nagrywania. Klatki nie przechodzą przez granicę okien: gra koduje je u siebie i oddaje gotowe bajty, dlatego działa to także na telefonie, gdzie nagrywania ekranu w przeglądarce nie ma.
klyo.canvas(mojePlotno);
Jak zareagować, gdy strona prosi o ciszę
Gracz gra w małym oknie przy biurku i wycisza portal. Strona nie może uciszyć twojej gry z zewnątrz (przeglądarka na to nie pozwala), więc mówi ci o tym, a ty decydujesz: wyciszasz miksera, zatrzymujesz muzykę. Bez tego wywołania nic się nie dzieje i nic się nie psuje.
klyo.onSound((on) => {
mikser.mute = !on;
});
Jak dobrać sterowanie do urządzenia
Dotyk czy klawiatura, ile pikseli, bez zgadywania po szerokości ekranu. Odpowiedź: { touch, width, height }.
const d = klyo.device();
if (d.touch) pokazPrzyciskiNaEkranie();
Jak zagrać online w kilka osób
Pokój z kodem (6 znaków) do wysłania znajomym albo szybkie kojarzenie w obrębie gry. Serwer pilnuje kolejności tur i zapisuje ruchy, a reguły sprawdza sama gra. Ruch i wiadomość mają do 1 KB, pokój na tury do 64 osób, na żywo do 16. Partię kończy move z result.winner: z tego liczy się ranking wygranych (klyo.online.ranking), a szybki mecz dobiera gracza o podobnym bilansie. W pokoju na żywo (mode: 'realtime') send i onMessage jadą kanałem UDP do serwera meczów klyo, do 120 wiadomości na sekundę; wysyłasz bajty (Uint8Array), napis albo obiekt do ok. 1 KB i odbiorca dostaje ten sam typ. Wiadomość send może zginąć po drodze jak każdy pakiet UDP, więc nadaje się do stanu, który zaraz i tak się odświeży. Zdarzenie, które musi dojść (strzał, trafienie, podniesienie), wysyłaj przez klyo.online.act, także w grze bez zasad: zestaw wysyła je trzy razy, a odbiorca dostaje raz. klyo.online.net() mówi, czym jedzie gra i jaki jest ping. Gdy UDP nie przejdzie, te same wywołania jadą zapasowym połączeniem (20 na sekundę). Klucze odpowiedzi po angielsku: room.code, room.me, room.host, room.turn, room.players.
klyo.online.quick((o) => {
if (o.ok) pokazKod(o.room.code);
});
klyo.online.onStart((r) => zacznij(r.players, r.turn));
klyo.online.onMove((m) => zastosuj(m.who, m.move));
// gdy klyo.online.room().turn === klyo.online.room().me:
klyo.online.move({ from: 12, to: 16 });
Jak dać graczom lobby bez pisania go samemu
Okno „Zagraj online” (szybki mecz z graczem o podobnym bilansie, własny pokój z kodem, link do wysłania znajomemu, lista czekających pokoi, najlepsi gracze i twój bilans) rysuje portal, nie gra. Gra woła jedno wywołanie i dostaje odpowiedź, gdy partia rusza. Link z kodem (?pokoj=KOD) otwiera stronę gry i sam dołącza; po odświeżeniu strony resume wraca do partii z listą ruchów.
klyo.online.lobby({ players: 2 }, (o) => {
if (o.ok) zacznij(o.room);
});
Jak mieć jedną pulę graczy na swojej stronie i na innym portalu
Te same pokoje działają poza klyo. Na swojej stronie albo na innym portalu z grami w przeglądarce wczytaj nasz most pokoi przed zestawem: gra łączy się wtedy z pokojami klyo jako gość, a jej gracze spotykają graczy klyo w tych samych pokojach na żywo. Most obsługuje pokoje na żywo (szybki mecz, dołączanie, start, wiadomości, kanał meczu, drużyny i mapy); pokoje turowe zostają na stronach klyo. Gość nie ma dostępu do konta klyo, płatności ani panelu. Wyniki, zapis postępu i nagrywanie działają tylko na stronach klyo. Domena musi najpierw trafić na naszą listę: napisz do nas adres swojej strony, a ją dopuścimy.
<script src="https://games.klyo.pl/sdk/klw-mini.js"></script>
<script src="https://games.klyo.pl/sdk/pokoj-most.js"></script>
<script>
window.klyoMostPokoi = klyoPokojMost({ slug: "twoja-gra", nick: () => playerName });
</script>
<script src="https://games.klyo.pl/sdk/klyo-gry-sdk.js"></script>
Gra multiplayer z własnym serwerem meczów
Masz już serwer (Photon, Colyseus, własny WebSocket) i grę na swojej stronie? Nie przenosisz niczego: wersja na klyo łączy się z tym samym serwerem, więc gracze z klyo i z twojej strony grają w tych samych meczach. Tak samo robi CrazyGames: hostuje pliki gry, a serwer meczów ma twórca. W studiu, w ostatnim kroku kreatora „Treść”, podajesz adres serwera i politykę prywatności gry; człowiek z klyo zatwierdza je, zwykle w ciągu dnia. Do tego czasu paczka łącząca się z tym serwerem nie wejdzie do katalogu. Wpuszczamy tylko ten jeden adres i tylko w twojej grze. Warunki: gracz na klyo gra jako gość (bez logowania do twoich kont i bez płatności w grze), a gra ma nasz zestaw (gotowość i wyniki). Strona gry mówi graczowi, że mecze prowadzi twój serwer, i linkuje twoją politykę prywatności. Gra z własnym serwerem działa w przeglądarce; do aplikacji klyo na telefony na razie nie trafia.
// bez zmian w kodzie gry: ten sam adres co na twojej stronie
const ws = new WebSocket("wss://eu1.twoja-gra.com/ws");
klyo.ready();
// po meczu:
klyo.score(punkty);
Kompletny przykład: kółko i krzyżyk online (cały plik)
Wklej do index.html, dodaj zestaw i wydaj. Gospodarz gra krzyżykiem, serwer pilnuje, kto ma ruch, a plansza wraca po odświeżeniu.
<!doctype html>
<meta charset="utf-8">
<script src="https://games.klyo.pl/sdk/klyo-gry-sdk.js"></script>
<div id="board"></div><p id="status"></p>
<script>
var B = document.getElementById("board"), S = document.getElementById("status");
var cells = ["", "", "", "", "", "", "", "", ""], mark = "";
function me() { var r = klyo.online.room(); return r ? r.me : ""; }
function draw() { var h = ""; for (var i = 0; i < 9; i++) h += '<button data-i="' + i + '">' + (cells[i] || "\u00b7") + "</button>"; B.innerHTML = h; }
function won() { var L = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]];
return L.some(function (l) { return cells[l[0]] && cells[l[0]] === cells[l[1]] && cells[l[0]] === cells[l[2]]; }); }
B.addEventListener("click", function (e) {
var i = e.target.getAttribute("data-i"), r = klyo.online.room();
if (i === null || cells[i] || !r || r.turn !== r.me) return; // serwer pilnuje, kto ma ruch; gra sprawdza reguły
cells[i] = mark; draw();
klyo.online.move({ i: +i }, won() ? { end: true, result: { winner: r.me } } : null);
});
klyo.online.onStart(function (r) { mark = r.host === me() ? "X" : "O"; cells = ["", "", "", "", "", "", "", "", ""]; draw(); S.textContent = "Gra! Ty: " + mark; });
klyo.online.onMove(function (m) { if (m.who !== me()) { cells[m.move.i] = mark === "X" ? "O" : "X"; draw(); } S.textContent = m.turn === me() ? "Twój ruch" : "Ruch przeciwnika"; });
klyo.online.onEnd(function (z) { S.textContent = z.result && z.result.winner === me() ? "Wygrana!" : "Koniec partii"; });
klyo.ready();
klyo.online.resume(function (r) { // powrót po odświeżeniu albo z linku ?pokoj=KOD
if (r.ok) { r.moves.forEach(function (m) { cells[m.move.i] = m.who === r.room.host ? "X" : "O"; }); draw(); return; }
klyo.online.lobby({ players: 2 }, function (o) { if (!o.ok) S.textContent = "Zagraj, gdy będziesz gotowy."; });
});
</script>
Jak sprawdzić, dlaczego gracze odchodzą
Bez żadnego kodu zestaw klyo zapisuje sześć kroków każdej sesji: wejście na stronę gry, Zagraj, wczytanie (klyo.ready), pierwszy ruch, 30 sekund gry i wynik, osobno na telefonie i komputerze, oraz mapę kliknięć. W studiu, w „Wyniki i oceny”, widzisz, na którym kroku ludzie wychodzą i ile gra się wczytuje. Dwie linijki dają więcej: klyo.level(3, "complete") pokazuje, na którym poziomie odpadają, a klyo.event("monety", 50) liczy Twoje zdarzenia. To samo dostaje Twój asystent AI przez narzędzie MCP klyo_game_analytics, razem z zadaniami: co poprawić i dlaczego. Do serwera idą same liczby, bez danych osób.
klyo.level(3, "start"); // poziom 3 się zaczął
klyo.level(3, "complete"); // przeszedł
klyo.level(3, "fail"); // przegrał
klyo.event("sklep_otwarty");
klyo.event("monety", 50);
Jak wskazać moment, który wart jest klipu
Gra wie najlepiej, kiedy dzieje się coś, co warto pokazać: combo, wybuch, przejście poziomu, przegrana o włos. Jedno wywołanie stawia znacznik na osi czasu nagrania. Edytor klipu sam zaznacza odcinek wokół ostatniego znacznika, a gracz nie szuka momentu po sekundzie. Rekord z klyo.wynik ma pierwszeństwo. Rodzaj to krótkie słowo bez spacji, dane to mały obiekt do podpisu klipu. Nic nie idzie do sieci; bez nagrywania znacznik po prostu przepada.
klyo.moment("combo", { seria: 12 });
Wspólny turniej tygodnia: API 1.2.0
Edycja zmienia się automatycznie w poniedziałek o 00:00 UTC. Serwer oblicza wynik z ruchów i zapisuje najlepszą ukończoną próbę. Zwykłe rekordy gry pozostają osobno.
Właściciel najpierw włącza zainstalowany moduł reguł swojej gry. Obecnie dostępny: blockfall-weekly-v1. Inna gra wymaga własnego modułu reguł po stronie serwera.
klyo.league.standings({scope: 'week'}, showBoard);
klyo.league.start(crypto.randomUUID(), resumeRun);
// Keep run and base; retry identical moves after a lost acknowledgement.
klyo.league.moves(run, base, [column], acceptServerState);
klyo.league.finish(run, moveCount, showConfirmedScore);
Rekordy zwykłej gry: standings({scope:"classic"}). Są zgłoszone przez klienta, nie zweryfikowane ruchem. record({}) zwraca profil i requiredConsent. Jawna publikacja wymaga {score, gameRank, publish:true, consentVersion:requiredConsent, eligible16:true}; nie ustawiaj zgody automatycznie. record({score,gameRank}) aktualizuje tylko opublikowany wpis. record({publish:false}) wycofuje publikację bez zmiany prywatnej gry. data i erase obejmują obie tabele.
| SDK | RPC v1 | Argumenty |
|---|---|---|
klyo.league.standings | gry.liga.tablica.v1 | options, callback |
klyo.league.start | gry.liga.start.v1 | requestId string or {requestId, gameRank?}, callback |
klyo.league.moves | gry.liga.ruchy.v1 | run, base, columns, callback |
klyo.league.finish | gry.liga.koniec.v1 | run, moves, callback |
klyo.league.data | gry.liga.dane.v1 | options, callback |
klyo.league.erase | gry.liga.usun.v1 | confirm, callback |
klyo.league.record | gry.liga.rekord.v1 | options, callback |
Tożsamość nadaje zalogowany host Klyo lub zweryfikowany podpis Facebooka. Konta tych dostawców nie są automatycznie łączone. Przyszłe aplikacje Klyo Games mogą użyć tego samego mostu SDK; ta wersja nie dostarcza aplikacji mobilnej.
Eksport danych jest stronicowany po 10 prób (pole next); usunięcie wymaga confirm: "DELETE". Próby: 90 dni, edycje tygodniowe: 52 tygodnie, rekord turniejowy: do usunięcia. Przy błędzie SERVER_BUSY ponów z opóźnieniem, zachowując identyfikator operacji.
Jak zbudować grę pod rekordy
Co gra dostaje za darmo. Kafel na hubie rekordów (games.klyo.pl/pl/rekordy/) z rekordem od zawsze i podium, miejsce w tabeli medalowej dnia (złoto, srebro, brąz za miejsca 1–3 w każdej grze), wpis na pasku „ostatnie rekordy” na żywo, plakietkę „Dziś prowadzi X” na kaflu w katalogu i powiadomienie „X cię wyprzedził” dla graczy z kontem. Warunek jest jeden: gra woła klyo.wynik.
Trzy wywołania i gotowe. Na starcie klyo.ready(), w trakcie partii klyo.progress(punkty) (żeton „#14 · 320 do X” pod grą), na końcu klyo.score(punkty, cb), a odpowiedź ma wszystko na ekran końca: pozycję dziś ze skokiem, w tygodniu, od zawsze i gracza tuż nad. Jeden najlepszy wynik na urządzenie dziennie: dziesięć partii z rzędu nie zajmuje dziesięciu miejsc.
Próg wyniku. W studiu, w wierszu gry, ustaw najwyższy wynik, jaki gra może dać. Kafel dostaje znak „próg ✓”, a wynik ponad próg odpada od razu. Bez progu tablica działa, ale kafel ma znak „bez progu”, a wynik ponad dziesięć razy wyższy od kolejnego (przy co najmniej dziesięciu wpisach) jest „do sprawdzenia”. Wpis możesz usunąć w Karcie gry.
Z asystentem AI (MCP). Podłącz klyo do swojego asystenta i powiedz: „dodaj tablicę wyników klyo do tej gry”. Narzędzie klyo_game_sdk daje mu ten sam opis, co tutaj: wywołania, wzorzec start → postęp → wynik, próg. Nową paczkę wysyła klyo_update_game.
Instrukcja krok po kroku: tablica wyników w grze HTML5
Czego zestaw nie robi i czego nie wolno wgrać
Gra nie może zawierać własnych reklam. Żadnej obcej sieci: AdMob, AdSense, Unity Ads, AppLovin, ironSource, Poki, CrazyGames ani podobnych. Sito przy wgrywaniu odrzuca taką paczkę i podaje nazwę znalezionej sieci.
Dlaczego tak. Reklamy odtwarza nasza strona wokół ramki z grą. Dzięki temu jest jedno konto wydawcy, jedno rozliczenie i sprawdzalny udział twórcy. Dwóch wydawców na jednej stronie to dla Google nieprawidłowość karana wyłączeniem konta: naszego i pośrednio twojego.
Gra nie sięga do strony ani do serwera. Nie ma dostępu do ciasteczek, do konta gracza ani do danych innych gier: stoi na własnym adresie i rozmawia ze stroną wyłącznie tymi wywołaniami. Dlatego możemy przyjmować cudze gry, nie czytając ich kodu linia po linii.
Do przetestowania przed pierwszą reklamą. Przerwa i nagroda działają w podglądzie i na portalu także wtedy, gdy dla gracza nie ma reklamy: zamiast niej strona pokazuje krótką zaślepkę i odpowiada dokładnie tak, jak z prawdziwą reklamą, więc całą mechanikę bonusu zbudujesz i przetestujesz przed pierwszą złotówką.
Co się dzieje, gdy ktoś otworzy grę poza klyo
Nic się nie psuje. Przerwa wraca natychmiast, wynik i zapis zostają w pamięci przeglądarki, a klip po prostu nie ma gdzie się zapisać. Tak samo w ramce na cudzej stronie, na przykład twojej albo na itch.io: zestaw rozpoznaje, że strona nad grą nie jest nasza, i odpowiada od razu (w Chrome, Edge i Safari zawsze, w Firefoksie, gdy strona podaje swój adres). Możesz więc trzymać jedną wersję gry na wszystko i nie potrzebujesz osobnej paczki dla nas.
Klyo Kit: szkielet gry na poziomie studia
Dwa znaczniki i jedno wywołanie. Kit daje to, co każde studio ma wspólne: menu, pauzę, ekran końca z rekordem i pozycją na tablicy, ustawienia (dźwięk, motyw jasny/ciemny, język), sterowanie dotykiem, myszą, klawiaturą i padem jednym zdarzeniem, płótno na dowolny ekran z wcięciami iPhone’a, dźwięk bez plików (syntezowany, z wznowieniem po powrocie z tła), „juice” (tweeny, drżenie, cząsteczki, błysk), zapis między urządzeniami, tryby: sam, na jednym urządzeniu (oddaj telefon), online na link. Ty piszesz tylko rozgrywkę.
<script src="https://games.klyo.pl/sdk/klyo-gry-sdk.js"></script>
<script src="https://games.klyo.pl/sdk/klyo-kit.js"></script>
<script>
var gra = klyoKit.start({ nazwa: "Moja gra", tryby: ["solo", "hotseat", "online"], uklad: "oba",
naStart: function (tryb) { nowaPartia(); } });
var c = gra.plotno(), g = c.getContext("2d"); // cały ekran, DPR, resize
gra.on("tap", function (d) { /* dotyk i mysz razem */ gra.dzwiek.graj("zbior"); gra.juice.czastki(d.x, d.y); });
gra.koniec({ wygrana: true, wynik: 120 }); // ekran końca + tablica + rekord
</script>
- Gra referencyjna na kicie: Statki (solo, na jednym urządzeniu, online na link, ~200 linii). Przeciwnika do gier turowych daje
gra.ai.minimax, a sterowanie kilkoma palcami na jednym ekraniegra.wskazniki. Reszta jest w kicie. - Przez asystenta:
klyo_game_scaffoldzwraca pliki-startery i pełne API; asystent nie pisze menu, pauzy ani dźwięku drugi raz. - Bez zewnętrznych arkuszy i czcionek: hosty gier mają
style-src 'self', więc kit ma CSS wbudowany, czcionka systemowa, kolory zgra.motyw.paleta.
Gra na każdym ekranie: czego wymagamy i co mierzymy
Gra dostaje u nas cały prostokąt sceny, a w pełnym ekranie cały ekran urządzenia: na telefonie „Zagraj” otwiera pełny ekran w tym samym geście, gra pozioma na pionowym telefonie dostaje ramkę obróconą o 90°, a żaden gest nie idzie do przeglądarki. Gra musi więc układać się do dowolnych proporcji, od 390×844 do 2400×1560.
- Układ do dowolnych proporcji. Nasłuchuj
resize, skaluj płótno doinnerWidth × innerHeight; żadnego sztywnego 1280×720 z pasami. - Dotyk.
pointerdown/pointermovealbotouchstart/touchmovez{ passive: false }ipreventDefault()na płótnie oraztouch-action: none. Sterowanie dotykiem to stuknięcie i przeciągnięcie. Na telefonie nie ma najechania kursorem, więc celowanie „przy ruchu bez przycisku” tam nie istnieje. Gra bez nasłuchu dotyku dostaje w studiu zadanie „tylko komputer”. - Czytelność. Najmniejszy tekst ≥ 10 px CSS przy szerokości 390 px i przy devicePixelRatio 1.
- Układ przy wydaniu. Zadeklaruj poziom, pion albo oba, a portal sam prosi o obrót i obraca ramkę; nie blokuj orientacji w grze.
- Dźwięk. Start po pierwszym geście gracza; po powrocie z tła (iPhone) wznów AudioContext w geście.
- Waga i czas. Pierwsze pobranie ≤ 20 MB na telefon, pierwsza klatka gry ≤ 20 s, ścieżki względne.
- Sprawdź u siebie, zanim wgrasz.
node klyo-test.mjs http://localhost:8080/ moja-gra ./klyo-test --uklad=pion. Plik /sdk/klyo-test.mjs mierzy dokładnie to, co my przy publikacji, z tymi samymi progami (Node 22 + Chrome/Chromium);--ukladto układ, który zadeklarujesz przy wydaniu (pion | poziom | oba). Przed wydaniem dodaj--slaby-telefon --jezyki: tani telefon (procesor cztery razy wolniejszy, słaba sieć) oraz ta sama gra po polsku i po angielsku, z miniaturą każdego języka.
Przy publikacji otwieramy grę w czterech ekranach (telefon w pionie i w poziomie z dotykiem, tablet, komputer) i mierzymy: przewijanie w ramce, ułamek ekranu zajęty przez grę, najmniejszy tekst, nasłuchy dotyku, wagę pierwszego pobrania i czas wczytania. Wynik z miniaturami widzisz w Karcie gry w studiu, a twój asystent w klyo_game_diagnostics. Sami nie zgadujemy: to samo widzi gracz.
Czego wymagamy od paczki
- Plik index.html w katalogu głównym paczki ZIP. Od niego zaczyna się gra.
- Gra ma działać bez instalacji i bez konta, w przeglądarce, także na telefonie.
- Do 350 MB. Sito sprawdza rozmiar, brakujące pliki, obce sieci reklamowe i ślady złośliwego kodu w kilkanaście sekund.
- Ankieta wieku wypełniana przy wgrywaniu daje etykietę, która decyduje o widoczności i o wejściu do aplikacji sklepowych.