Перейти к основному содержимому
🎉 GP CONF 2026: Конференция о рынке WEB-игр 👾 23 сентября | Подробнее

Состояние игрока

Состояние игрока содержит данные, которыми управляет отдельный игрок. Каждый игрок отправляет свои обновления хосту, а хост распространяет итоговую карту состояний по комнате.

Обычно здесь хранятся координаты, направление, анимация, здоровье и счёт игрока.

Список методов

Действия:

Свойства:

События:

  • playersUpdated - отслеживать обновления карты состояний.
  • becameHost - настроить инициализацию игроков после миграции хоста.

Определение схемы игрока

Определите схему до запуска игры:

gp.multiplayer.definePlayerSchema({
x: { interpolate: true },
y: { interpolate: true },
direction: { interpolate: false },
hp: { interpolate: false },
color: { readonly: true },
});

Интерполяция — это плавный переход числового значения между полученными обновлениями. Например, если координата изменилась с x: 100 на x: 150, SDK покажет промежуточные позиции, а не мгновенно переместит объект.

Включайте интерполяцию для значений, которые должны изменяться плавно, например координат. Отключайте её для значений, которые должны применяться сразу, например здоровья, состояния анимации или идентификатора предмета.

Инициализация игроков на хосте

Инициализатор выполняется на хосте и возвращает начальное состояние каждого игрока:

function getPlayerColor(playerId) {
const colors = ['#ff6b6b', '#4ecdc4', '#45b7d1', '#f7dc6f'];
return colors[playerId % colors.length];
}

function initializePlayer(playerId, playerInfo) {
return {
x: 100 + (playerId % 5) * 60,
y: 200,
direction: 1,
hp: 100,
color: getPlayerColor(playerId),
};
}

async function configurePlayerInitialization() {
if (!gp.multiplayer.isHost) {
return;
}

await gp.multiplayer.setPlayerInitializer(initializePlayer);
}

gp.multiplayer.on('becameHost', configurePlayerInitialization);

Хост выбирается асинхронно. Вызов setPlayerInitializer() после получения роли хоста также инициализирует уже подключённых игроков, для которых ещё нет состояния.

После подключения обработайте случай, когда роль уже выбрана:

await gp.multiplayer.connect({ channelId });
await configurePlayerInitialization();

Не удаляйте подписку на becameHost: текущий игрок может стать хостом позднее.

Инициализатор также может возвращать Promise:

async function initializePlayer(playerId) {
const spawn = await loadSpawnPoint(playerId);

return {
x: spawn.x,
y: spawn.y,
hp: 100,
color: getPlayerColor(playerId),
};
}

Обновление текущего игрока

Используйте цикл тиков SDK для игровой логики. Следующий пример ожидает начальное состояние, обрабатывает локальное движение и отправляет только поля, которыми управляет игрок:

const keys = new Set();

window.addEventListener('keydown', (event) => keys.add(event.code));
window.addEventListener('keyup', (event) => keys.delete(event.code));

let localX = null;
let localY = null;
let direction = 1;

function updateLocalPlayer(delta) {
const myState = gp.multiplayer.myState;

if (localX === null || localY === null) {
if (!myState) {
return;
}

localX = myState.x;
localY = myState.y;
}

const speed = 200;
const distance = speed * (delta / 1000);

if (keys.has('ArrowLeft')) {
localX -= distance;
direction = -1;
}

if (keys.has('ArrowRight')) {
localX += distance;
direction = 1;
}

gp.multiplayer.setPlayerState({
x: localX,
y: localY,
direction,
});
}

gp.multiplayer.onTick(updateLocalPlayer);

setPlayerState() принимает частичное состояние. SDK объединяет его с существующим состоянием и не отправляет обновление, если переданные значения не изменились.

Локальное состояние текущего игрока доступно через:

const myState = gp.multiplayer.myState;

Отрисовка всех игроков

playersState — это Map, где ключом является playerId, а значением — последнее состояние игрока:

function renderPlayers() {
for (const [playerId, state] of gp.multiplayer.playersState) {
drawPlayer({
id: playerId,
x: state.x,
y: state.y,
color: state.color,
hp: state.hp,
});
}

requestAnimationFrame(renderPlayers);
}

requestAnimationFrame(renderPlayers);

Координаты удалённых игроков уже прошли через буфер интерполяции SDK. Для текущего игрока используется локальное состояние без задержки интерполяции.

Используйте playersUpdated, если игре нужно реагировать на изменение карты состояний вне цикла отрисовки:

function onPlayersUpdated(players) {
updatePlayersPanel(players);
}

gp.multiplayer.on('playersUpdated', onPlayersUpdated);

Подписываться на playersUpdated только ради отрисовки необязательно. Достаточно читать playersState во время рендера.

Выбор режима синхронизации

Выберите режим до запуска игрового цикла:

gp.multiplayer.setMode('smooth');

Отличия fast и smooth описаны в разделе Режимы синхронизации.

Остановка цикла игрока

Передайте в offTick() ту же ссылку на функцию, которая использовалась при подписке:

gp.multiplayer.offTick(updateLocalPlayer);
gp.multiplayer.off('playersUpdated', onPlayersUpdated);
gp.multiplayer.off('becameHost', configurePlayerInitialization);

Оставайтесь на связи

С другими документами раздела вы можете ознакомиться здесь. Для начала работы с GamePush ознакомьтесь с нашими туториалами.

Сообщество GamePush в Telegram: @gs_community.

Для ваших обращений e-mail: official@gamepush.com

Желаем вам успехов!