Przejdź do treści
klyogames

Co dodajesz?

Jedno konto dla gracza i twórcy. Wpis i klip trafiają do społeczności, gra do katalogu po sprawdzeniu.

Gra (paczka ZIP)Własny adres i statystyki, a udział w reklamach, gdy je uruchomimy. Publikacja po automatycznym sprawdzeniu. Klip z gryNagraj 15–30 s rozgrywki jednym kliknięciem w studiu. Wpis do społecznościTekst, zdjęcia albo wideo do 30 s: pytanie, prośba o testy, premiera.

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.

SDKRPC v1Argumenty
klyo.league.standingsgry.liga.tablica.v1options, callback
klyo.league.startgry.liga.start.v1requestId string or {requestId, gameRank?}, callback
klyo.league.movesgry.liga.ruchy.v1run, base, columns, callback
klyo.league.finishgry.liga.koniec.v1run, moves, callback
klyo.league.datagry.liga.dane.v1options, callback
klyo.league.erasegry.liga.usun.v1confirm, callback
klyo.league.recordgry.liga.rekord.v1options, 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ę.

&lt;script src=&quot;https://games.klyo.pl/sdk/klyo-gry-sdk.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://games.klyo.pl/sdk/klyo-kit.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;
var gra = klyoKit.start({ nazwa: &quot;Moja gra&quot;, tryby: [&quot;solo&quot;, &quot;hotseat&quot;, &quot;online&quot;], uklad: &quot;oba&quot;,
  naStart: function (tryb) { nowaPartia(); } });
var c = gra.plotno(), g = c.getContext(&quot;2d&quot;);           // cały ekran, DPR, resize
gra.on(&quot;tap&quot;, function (d) { /* dotyk i mysz razem */ gra.dzwiek.graj(&quot;zbior&quot;); gra.juice.czastki(d.x, d.y); });
gra.koniec({ wygrana: true, wynik: 120 });              // ekran końca + tablica + rekord
&lt;/script&gt;
  • 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 ekranie gra.wskazniki. Reszta jest w kicie.
  • Przez asystenta: klyo_game_scaffold zwraca 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 z gra.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 do innerWidth × innerHeight; żadnego sztywnego 1280×720 z pasami.
  • Dotyk. pointerdown/pointermove albo touchstart/touchmove z { passive: false } i preventDefault() na płótnie oraz touch-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); --uklad to 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.