Moninpelin framework, jota kehittäjät rakastavat
Open-source, tuotannossa todistettu ja rakennettu reaaliaikaisiin peleihin. Ilmainen ikuisesti.
npm create kidsgames-app@latest ./my-server Поддерживает ваш любимый движок и платформу
- Huijauksen esto arkkitehtuurin tasolla
- Sisäänrakennettu matchmaking
- Tilan synkronointi, joka vain toimii
- Skaalaus 10:stä yli 10 000 CCU:hun
- Ota käyttöön itse tai käytä KidsGames Cloudia
- Käytä sinulle tuttuja työkaluja
- Ilmainen ikuisesti (MIT-lisenssi)
Как это работает
От нуля до мультиплеера
Опишите комнаты, синхронизируйте состояние, подключайте клиентов. Полноценный мультиплеерный сервер в несколько строк кода.
import { Room } from "kidsgames";
class MyRoom extends Room { maxClients = 4; onCreate(options) {/* your code */} onAuth(client, options) {/* your code */} onJoin(client, options) {/* your code */} onLeave(client) {/* your code */} onDispose() {/* your code */}}import { defineServer, defineRoom } from "kidsgames";import { MyRoom } from "./MyRoom";
export default defineServer({ rooms: { my_room: defineRoom(MyRoom), },});import { type, Schema, MapSchema, ArraySchema } from "@kidsgames/schema";
export class Player extends Schema { @type("string") name: string; @type("number") position: number;}
export class MyState extends Schema { @type({map: Player}) players = new MapSchema<Player>(); @type(["number"]) board = new ArraySchema<number>([0, 0, 0, 0, 0, 0, 0, 0, 0]); @type("string") currentTurn: string;}import { Room } from "kidsgames";import { MyState } from "./MyState";
export class MyRoom extends Room { state = new MyState();
onCreate() { // room has been created }
onJoin(client, options) { // new client joined the room this.state.players.set(client.sessionId, new Player()); this.state.currentTurn = client.sessionId; }
onLeave() { // client left the room this.state.players.delete(client.sessionId); }}import { Client } from "@kidsgames/sdk";
// Initialize SDKconst client = new Client("https://0.0.0.0:2567");
// Connect to a roomconst room = await client.joinOrCreate("my_room");import { Client, Callbacks } from "@kidsgames/sdk";
const client = new Client("https://0.0.0.0:2567");const room = await client.joinOrCreate("my_room", { /* client options */});
const callbacks = Callbacks.get(room);
// on player added/joincallbacks.onAdd("players", (player, sessionId) => { console.log("Player added!", player, sessionId); // on player "position" change callbacks.listen(player, "position", (position, previousPosition) => { console.log("player position changed!", { position, previousPosition }); });});
// on player removed/leftcallbacks.onRemove("players", (player, sessionId) => { console.log("Player removed!", player, sessionId);});
// on "board" changecallbacks.onChange("board", (value, index) => { console.log("board item changed to", value, "at", index);});
// on "currentTurn" changecallbacks.listen("currentTurn", (currentTurn, previousValue) => { console.log("currentTurn:", currentTurn); console.log("currentPlayer:", room.state.players.get(currentTurn));});Опишите комнату (Room)
Комнаты — основной строительный блок. Каждая комната выполняет игровую логику, обрабатывает соединения и управляет состоянием. Опишите хуки жизненного цикла: подключение, отключение и получение сообщений от игроков.
Откройте для матчмейкинга
Зарегистрируйте тип комнаты одной строкой. Остальное берёт на себя KidsGames — создаёт новые экземпляры по мере необходимости, заполняет их и направляет игроков в нужную комнату.
Опишите состояние (state)
Опишите игровое состояние с помощью классов схемы с декораторами. KidsGames отслеживает изменения и синхронизирует их со всеми клиентами, используя бинарную дельта-компрессию.
Меняйте состояние
Просто изменяйте объекты состояния как обычный JavaScript. KidsGames обнаруживает изменения и рассылает подключённым клиентам только дельты.
Подключитесь с клиента
Подключитесь к серверу и войдите в комнату в несколько строк кода. Если свободной комнаты нет, сервер создаёт её автоматически.
Слушайте изменения состояния
Реагируйте на изменения состояния через точечные колбэки. Точно знайте, когда игроки подключаются, отключаются или обновляется любое состояние.
Опишите комнату (Room)
Комнаты — основной строительный блок. Опишите хуки жизненного цикла: подключение, отключение и получение сообщений от игроков.
import { Room } from "kidsgames";
class MyRoom extends Room { maxClients = 4; onCreate(options) {/* your code */} onAuth(client, options) {/* your code */} onJoin(client, options) {/* your code */} onLeave(client) {/* your code */} onDispose() {/* your code */}}Откройте для матчмейкинга
Зарегистрируйте тип комнаты одной строкой. Остальное берёт на себя KidsGames.
import { defineServer, defineRoom } from "kidsgames";import { MyRoom } from "./MyRoom";
export default defineServer({ rooms: { my_room: defineRoom(MyRoom), },});Опишите состояние (state)
Опишите игровое состояние с помощью классов схемы с декораторами. KidsGames отслеживает и синхронизирует изменения автоматически.
import { type, Schema, MapSchema, ArraySchema } from "@kidsgames/schema";
export class Player extends Schema { @type("string") name: string; @type("number") position: number;}
export class MyState extends Schema { @type({map: Player}) players = new MapSchema<Player>(); @type(["number"]) board = new ArraySchema<number>([0, 0, 0, 0, 0, 0, 0, 0, 0]); @type("string") currentTurn: string;}Меняйте состояние
Просто изменяйте объекты состояния. KidsGames обнаруживает изменения и рассылает дельты.
import { Room } from "kidsgames";import { MyState } from "./MyState";
export class MyRoom extends Room { state = new MyState();
onCreate() { // room has been created }
onJoin(client, options) { // new client joined the room this.state.players.set(client.sessionId, new Player()); this.state.currentTurn = client.sessionId; }
onLeave() { // client left the room this.state.players.delete(client.sessionId); }}Подключитесь с клиента
Войдите в комнату в несколько строк кода. Если свободной нет, сервер создаёт её сам.
import { Client } from "@kidsgames/sdk";
// Initialize SDKconst client = new Client("https://0.0.0.0:2567");
// Connect to a roomconst room = await client.joinOrCreate("my_room");Слушайте изменения состояния
Реагируйте на изменения состояния через точечные колбэки.
import { Client, Callbacks } from "@kidsgames/sdk";
const client = new Client("https://0.0.0.0:2567");const room = await client.joinOrCreate("my_room", { /* client options */});
const callbacks = Callbacks.get(room);
// on player added/joincallbacks.onAdd("players", (player, sessionId) => { console.log("Player added!", player, sessionId); // on player "position" change callbacks.listen(player, "position", (position, previousPosition) => { console.log("player position changed!", { position, previousPosition }); });});
// on player removed/leftcallbacks.onRemove("players", (player, sessionId) => { console.log("Player removed!", player, sessionId);});
// on "board" changecallbacks.onChange("board", (value, index) => { console.log("board item changed to", value, "at", index);});
// on "currentTurn" changecallbacks.listen("currentTurn", (currentTurn, previousValue) => { console.log("currentTurn:", currentTurn); console.log("currentPlayer:", room.state.players.get(currentTurn));});Клиентские SDK
Разрабатывайте на любой платформе
Подключайтесь к серверу KidsGames из любого движка, фреймворка или языка. Синхронизация состояния работает одинаково везде.
import { Client, Callbacks } from "@kidsgames/sdk";
const client = new Client("https://your-server.com");const room = await client.joinOrCreate("game_room");const callbacks = Callbacks.get(room);
callbacks.onAdd("players", (player, key) => { addSpriteForPlayer(player); callbacks.onChange(player, () => moveSprite(key, player.x, player.y));});
callbacks.onRemove("players", (player, key) => removeSpriteForPlayer(key));
room.send("move", { x: 10, y: 20 });import { Client } from "@kidsgames/sdk";import { useRoom, useRoomState } from "@kidsgames/react";
const client = new Client("https://your-server.com");
function Game() { const { room, isConnecting } = useRoom( () => client.joinOrCreate("game_room"), ); const state = useRoomState(room);
if (isConnecting) return <p>Connecting...</p>;
return ( <ul> {state?.players.map((player, key) => ( <li key={key}>Player at {player.x}, {player.y}</li> ))} </ul> );}using KidsGames;using KidsGames.Schema;
var client = new Client("https://your-server.com");var room = await client.JoinOrCreate<GameState>("game_room");var callbacks = Callbacks.Get(room);
callbacks.OnAdd(state => state.players, (sessionId, player) => { AddSpriteForPlayer(player); callbacks.OnChange(player, () => MoveSprite(sessionId, player.x, player.y));});
callbacks.OnRemove(state => state.players, (sessionId, player) => RemoveSpriteForPlayer(sessionId));
await room.Send("move", new { x = 10, y = 20 });var client: KidsGamesClient = KidsGames.create_client()client.set_endpoint("wss://your-server.com")var room: KidsGamesRoom = client.join_or_create("game_room")
room.joined.connect(func(): var callbacks = KidsGames.callbacks(room)
callbacks.on_add("players", func(player, key): add_sprite_for_player(player) callbacks.on_change(player, func(): move_sprite(key, player.x, player.y) ) )
callbacks.on_remove("players", func(player, key): remove_sprite_for_player(key) )
room.send("move", {"x": 10, "y": 20}))client = new KidsGamesClient("https://your-server.com");room = client.join_or_create("game_room");callbacks = KidsGamesCallbacks(room);
callbacks.on_add("players", function(player, key) { add_sprite_for_player(player); callbacks.on_change(player, function() { move_sprite(key, player.x, player.y); });});
callbacks.on_remove("players", function(player, key) { remove_sprite_for_player(key);});
room.send("move", { x: 10, y: 20 });local KidsGamesSDK = require "kidsgames.sdk"
local client = KidsGamesSDK.Client("https://your-server.com")client:join_or_create("game_room", function(room) local callbacks = KidsGamesSDK.callbacks(room)
callbacks:on_add("players", function(player, key) add_sprite_for_player(player) callbacks:on_change(player, function() move_sprite(key, player.x, player.y) end) end)
callbacks:on_remove("players", function(player, key) remove_sprite_for_player(key) end)
room:send("move", { x = 10, y = 20 })end)import io.kidsgames.Client;import io.kidsgames.schema.Callbacks;
var client = new Client("https://your-server.com");client.joinOrCreate("game_room", [], MyRoomState, function(err, room) { var callbacks = Callbacks.get(room);
callbacks.onAdd("players", (player, key) -> { addSpriteForPlayer(player); callbacks.onChange(player, () -> moveSprite(key, player.x, player.y)); });
callbacks.onRemove("players", (player, key) -> removeSpriteForPlayer(key));
room.send("move", {x: 10, y: 20});});#include "kidsgames.h"
kidsgames_client_t* client = kidsgames_client_new("https://your-server.com");kidsgames_room_t* room = kidsgames_join_or_create(client, "game_room");kidsgames_callbacks_t* callbacks = kidsgames_callbacks_get(room);
void on_player_add(kidsgames_state_t* player, const char* key) { add_sprite_for_player(player); kidsgames_on_change(callbacks, player, on_player_change, (void*)key);}
void on_player_change(kidsgames_state_t* player, void* ctx) { float x = kidsgames_get_float(player, "x"); float y = kidsgames_get_float(player, "y"); move_sprite((const char*)ctx, x, y);}
kidsgames_on_add(callbacks, "players", on_player_add, NULL);kidsgames_on_remove(callbacks, "players", on_player_remove, NULL);kidsgames_room_send(room, "move", data, data_len);const client = new KidsGames.Client("https://your-server.com");const room = await client.joinOrCreate("game_room");const callbacks = KidsGames.Callbacks.get(room);
callbacks.onAdd("players", (player, key) => { const sprite = runtime.objects.Player.createInstance("Game", player.x, player.y); callbacks.onChange(player, () => { sprite.x = player.x; sprite.y = player.y; });});
callbacks.onRemove("players", (player, key) => { // destroy sprite instance});
room.send("move", { x: 10, y: 20 });Konepellin alla
Arkkitehtuuri ja teknologiapino
Luotettava teknologiapino, jotta voit keskittyä peliin etkä pyörän uudelleen keksimiseen.
Node.js-ajonaika
Asynkroninen, tapahtumapohjainen JavaScript-ajonaika skaalautuvien verkkosovellusten rakentamiseen.
Verkkokuljetus
WebSockets kuljetuskerroksena; WebTransport-tuki on julkisella tiekartallamme.
Room-pohjainen järjestelmä
Stateful-huoneet luodaan asiakkaan pyynnöstä.
Viestien serialisointi
Binäärinen delta-serialisointi tilan synkronointiin ja nopein MessagePack-serialisoija kaikkeen muuhun.
Web- / API-reitit
Määrittele omat API-reittisi Expressin tai better-callin kautta.
Tietokanta ja todennus
Käytä suosikki-Node.js-työkalujasi. Valitset itse tietokannan ja todennuspalveluntarjoajan.
Skaalaa luottavaisin mielin
Skaalautuvuus
Yksinkertainen mutta tehokas skaalausstrategia
- Jaa huoneet palvelinten ja/tai prosessien kesken
- Matchmaking koko klusterin laajuisesti
- Hyödynnä kaikki käytettävissä olevat CPU-ytimet
- Yhdistä asiakkaat suoraan pyydettyihin huoneisiin
- Stateful-prosessit seuraavat itse omia huoneitaan
Kehittäjäkokemus
Työkalut
Sisäänrakennetut työkalut, jotka kulkevat mukanasi kehityksestä tuotantoon.
Asiakas-Playground
Luo asiakasyhteyksiä ja tutki dataa, jota vaihdat palvelimen kanssa.
Reaaliaikainen huoneiden tarkastelu
Selaa ja analysoi palvelimen luomien huoneiden listaa.
Yksikkötestaus
Apumetodit huoneiden testaamiseen suosikkitestausframeworkissasi.
Kuormitustestaus
Arvioi, miten palvelin käyttäytyy korkean kuorman alla.
Node.js-ekosysteemi
Liitä suosikkityökalusi KidsGames-palvelimeesi.
Нам доверяют
Нам доверяют игровые студии
Инди-разработчики и студии создают мультиплеерные игры в реальном времени на KidsGames.
Стать партнёромAloita työskentely
KidsGames Cloudin kehitystä rahoitetaan KidsGames Cloud -tilauksilla.
Käynnissä on kutsupohjainen suljettu beta — pyydä pääsy kokeillaksesi alustaa.




