Асинхронный мультиплеер

С помощью модуля ysdk.multiplayer вы можете создать соревновательный режим, похожий на онлайн-мультиплеер. При этом вам не нужно:

  • писать и поддерживать собственное серверное решение;
  • иметь критическую массу игроков, необходимую для быстрого поиска соперников.

Примеры жанров, кор-механику которых можно реализовать через SDK:

  • Головоломки: асинхронные сессии могут воспроизводиться на соседних игровых полях, можно добавить соперничество по времени или по очкам. Примеры подходящих игр: Косынка Онлайн! (от KosmosGames), Match Arena - Три в Ряд! (от PecPoc Piggy).
  • Раннеры и гонки: сессии соперников могут отрисовываться в виде «теней», перемещающихся по уровню одновременно с игроком (механика ghost driver). Примеры подходящих игр: Дикие Тачки 2 (от JL studio) в режиме «Скоростная Гонка», Дикие мотоциклы (от haoda games).
  • Стратегии и автобаттлеры: можно реализовать бои против тактик других игроков. Примеры подходящих игр: Ludus (от Positron Dynamics), Like a King (от Vladimir Saponenko), TOYS: Crash Arena (от Mad Pixel).

Концепция

  1. Пользователь А играет, SDK записывает ключевые события (нажатия клавиш, изменения состояния) и фиксирует их время.
  2. Эти события сохраняются на сервере как таймлайн (список транзакций).
  3. Когда пользователь Б запускает игру, в его сессию загружаются соперники из уже сохраненных таймлайнов.
  4. SDK воспроизводит действия соперников в реальном времени, создавая ощущение одновременной игры.

Инициализация и загрузка сессий

Чтобы начать работу с асинхронным мультиплеером, вызовите метод ysdk.multiplayer.sessions.init(). В нем происходят стартовая инициализация и загрузка игровых сессий оппонентов.

Метод возвращает массив загруженных сессий.

Параметр count определяет количество сессий для загрузки. Максимальное количество сессий в ответе — 10 шт.

Для выборки используются параметры meta1, meta2, meta3. Они имеют форму объектов { min: %number%, max: %number% } и задаются при сохранении сессии. К примеру, если в meta1 хранится счет в игре, а в meta2 — уровень игрока, вы можете загрузить сохраненные сессии, близкие по этим параметрам текущему пользователю.

Важно

Для загрузки сессий необходимо задать как минимум один из трех meta-параметров, а также значение параметра count больше нуля. В ином случае мультиплеер будет проинициализирован только на запись.

ysdk.multiplayer.sessions.init({
  count: 2, // Количество сессий оппонентов для загрузки (до 10).
  isEventBased: true, // Флаг для инициализации работы через события.
  maxOpponentTurnTime: 200, // Ограничение времени хода оппонента (мс).
  meta: {
    meta1: {
      min: 0,
      max: 6000,
    },
    meta2: {
      min: 2,
      max: 10,
    },
  },
}).then(opponents => console.log(opponents));
const work = async () => {
  const opponents = await ysdk.multiplayer.sessions.init({
    count: 2, // Количество сессий оппонентов для загрузки (до 10).
    isEventBased: true, // Флаг для инициализации работы через события.
    maxOpponentTurnTime: 200, // Ограничение времени хода оппонента (мс).
    meta: {
      meta1: {
        min: 0,
        max: 6000,
      },
      meta2: {
        min: 2,
        max: 10,
      },
    },
  });

  console.log(opponents);
}

work();

Формат ответа

[
  {
    id: string;
    meta: {
      meta1: number;
      meta2: number;
      meta3: number;
    };
    player: {
      avatar: string;
      name: string;
    };
    timeline: [
      {
        id: string;
        payload: object | string | undefined;
        time: number;
      },
      ...
    ];
  },
  ...
]

Параметр

Тип

Описание

id

string

Идентификатор сессии.

meta

object

Пользовательские параметры meta1, meta2, meta3. Например, счет в игре или уровень игрока.

player

object

Информация об игроке-сопернике:

  • avatar: string — URL аватара пользователя;
  • name: string — имя игрока.

timeline

array

Массив событий с таймингом, описывающий игровую сессию:

  • id: string — уникальный идентификатор события;
  • payload — данные события: информация, отражающая суть, причину изменений в игровом мире (например, новые координаты персонажа или нажатие кнопки мыши);
  • time: number — время от начала игры с поправкой на паузы (мс).

Запись игровой сессии

Внимание

Максимальный размер одной записанной сессии — 200 КБ.

Используйте SDK, чтобы записать игровые сессии пользователей (последовательность событий с метками времени). Событиями могут быть перемещения фигур на доске в головоломках или нажатие клавиш клавиатуры или мыши в раннерах.

В играх, где пользовательский ввод непрерывный, например в раннерах, события могут формироваться искусственно в заданный интервал времени, фиксируя показатели состояния персонажа — координаты, уровень энергии и т. д. Также это могут быть случайные события в игре — вознаграждения, землетрясения.

События, происходящие в игре, сохраняются в виде транзакций. У каждой транзакции есть:

  • id — уникальный идентификатор события;
  • payload — данные события: информация, отражающая суть, причину изменений в игровом мире (например, новые координаты персонажа или нажатие кнопки мыши);
  • time — время от начала игры с поправкой на паузы.

В течение игры сохраняйте payload с помощью метода commit(). Так сформируется список транзакций — таймлайн игровой сессии (timeline).

В конце игры сохраните сессию на сервере с помощью метода push(). После сохранения сессия может быть загружена и воспроизведена в следующей игре.

ysdk.multiplayer.sessions.commit()

Метод commit() фиксирует транзакции текущей игровой сессии. В него передаются данные события (payload).

Важно

Другие параметры транзакции — идентификатор (id) и время от начала игры (time) — рассчитываются в SDK, поэтому важно отправлять payload своевременно.

Пример использования

// Первая транзакция.
ysdk.multiplayer.sessions.commit({ x: 1, y: 2, z: 3, health: 67 });

// .......

// Следующая транзакция.
ysdk.multiplayer.sessions.commit({ x: 4, y: -2, z: 19, health: 15 });

// .......

ysdk.multiplayer.sessions.push()

Метод push() используется для сохранения таймлайна на удаленном сервере. Вызывается по завершению игры.

Значения meta1, meta2, meta3 задаются при сохранении сессии. Как минимум один из meta-параметров должен быть определен.

Пример использования

ysdk.multiplayer.sessions.push({ meta1: 12, meta2: -2 });

Работа с сессиями

Чтобы выбрать, как работать с загруженными сессиями оппонентов, в метод init() передайте нужное значение флага isEventBased:

  • true — работа через события;
  • false — самостоятельная обработка.

Клиент подписывается на события multiplayer-sessions-transaction и multiplayer-sessions-finish через ysdk.on(), а SDK сам загружает общую сессию и выдает события по указанным в ней временным меткам:

  • Во время игры транзакции соперников приходят в обработчик multiplayer-sessions-transaction в записанный момент от начала сессии, но с учетом ограничения времени хода оппонента (maxOpponentTurnTime, параметр метода init()).

  • Когда сессия заканчивается, вызывается обработчик multiplayer-sessions-finish с идентификатором соперника, чья игра закончилась.

ysdk.multiplayer.sessions.init({
  count: 2, // Количество сессий оппонентов для загрузки (до 10).
  isEventBased: true, // Флаг для инициализации работы через события.
  maxOpponentTurnTime: 200, // Ограничение времени хода оппонента (мс).
  meta: {
    meta1: {
      min: 0,
      max: 6000,
    },
    meta2: {
      min: 2,
      max: 10,
    },
  },
});

// Здесь приходит массив транзакций для выполнения в данный момент времени:
// текущая транзакция, а также транзакции, отставшие из-за возможных фризов игры.
ysdk.on('multiplayer-sessions-transaction', ({ opponentId, transactions }) = > {
  console.log(opponentId, transactions);
  // Применение данных transaction.payload на игровом поле.
});

ysdk.on('multiplayer-sessions-finish', (opponentId) => console.log(opponentId));

Старт и пауза мультиплеера управляются методами разметки геймплея:

// Старт мультиплеера.
ysdk.features.GameplayAPI.start();

// Пауза мультиплеера.
ysdk.features.GameplayAPI.stop();

Метод инициализации мультиплеера init() возвращает массив загруженных сессий оппонентов, содержащих в себе таймлайны с транзакциями.

Получите данные и обработайте их самостоятельно:

const start = (opponent) => {
  console.log('player', opponent.player);
  console.log('timeline', opponent.timeline);

  // Реализация механизма использования данных timeline и player.
}

const work = async () => {
  const opponents = await ysdk.multiplayer.sessions.init({
    count: 2, // Количество сессий оппонентов для загрузки (до 10).
    isEventBased: false, // Флаг для инициализации работы через события.
    maxOpponentTurnTime: 200, // Ограничение времени хода оппонента (мс).
    meta: {
      meta1: {
        min: 0,
        max: 6000,
      },
      meta2: {
        min: 2,
        max: 10,
      },
    },
  });

  console.log('opponents', opponents);

  for (let i = 0; i < opponents.length; i++) {
    start(opponents[i]);
  }
}

work();

Примечание

Сотрудники службы поддержки помогают разместить готовую игру на платформе Яндекс Игр. На прикладные вопросы о разработке и тестировании предметно ответят другие разработчики в Сообществе в Телеграме.

Если при использовании SDK Яндекс Игр вы столкнулись с проблемой или у вас появился вопрос, обратитесь в службу поддержки:

Написать в чат

Идентификатор сессии.

Пользовательские параметры meta1, meta2, meta3, которые задаются при сохранении сессии. Например, счет в игре или уровень игрока.

Информация об игроке-сопернике:

  • avatar: string — URL аватара пользователя;
  • name: string — имя игрока.

Массив событий с таймингом, описывающий игровую сессию:

  • id: string — уникальный идентификатор события;
  • payload — данные события: информация, отражающая суть, причину изменений в игровом мире (например, новые координаты персонажа или нажатие кнопки мыши);
  • time: number — время от начала игры с поправкой на паузы (мс).

Уникальный идентификатор события.

Данные события: информация, отражающая суть, причину изменений в игровом мире (например, новые координаты персонажа или нажатие кнопки мыши).

Время от начала игры с поправкой на паузы.

Предыдущая
Следующая