异步多人游戏

通过 ysdk.multiplayer 模块,您可以创建类似在线多人游戏的竞技模式。这样您无需:

  • 编写和维护自己的服务器解决方案;
  • 拥有快速寻找对手所需的临界玩家数量。

可以通过 SDK 实现核心机制的游戏类型示例:

  • 益智游戏: 异步会话可以在相邻的游戏板上播放,可以增加按时间或分数的竞争。适合的游戏示例:空当接龙在线! (来自 KosmosGames),Match Arena - 消消乐! (来自 PecPoc Piggy)。
  • 跑酷和赛车游戏: 对手的会话可以显示为“阴影”,与玩家一起在关卡中移动 (鬼魂驾驶机制)。适合的游戏示例:疯狂赛车 2 (来自 JL studio) 中的“极速竞赛”模式,疯狂摩托 (来自 haoda games)。
  • 策略和自动战斗游戏: 可以实现与其他玩家战术对抗的战斗。适合的游戏示例:Ludus (来自 Positron Dynamics),Like a King (来自 Vladimir Saponenko),TOYS: Crash Arena (来自 Mad Pixel)。

概念

  1. 用户 A 游戏时,SDK 记录关键事件(按键、状态变化)及其时间。
  2. 这些事件作为时间线(事务列表)保存在服务器上。
  3. 用户 B 启动游戏时,已保存的时间线中的对手将加载到他的会话中。
  4. SDK 实时重现对手的动作,营造同时游戏的感觉。

初始化和加载会话

要开始使用异步多人游戏,请调用方法 ysdk.multiplayer.sessions.init()。该方法进行初始初始化和加载对手的游戏会话。

该方法返回已加载会话的数组

参数 count 确定要加载的会话数量。响应中的最大会话数为 10 个。

用于筛选的参数有 meta1meta2meta3。它们的形式为对象 { 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

自定义参数 meta1meta2meta3。例如,游戏中的分数或玩家等级。

player

object

对手玩家信息:

  • avatar: string — 用户头像的URL;
  • name: string — 玩家的姓名。

timeline

array

描述游戏会话的事件时间线数组:

  • id: string — 事件的唯一标识;
  • payload — 事件数据:反映游戏世界中变化原因的信息(例如,角色的新坐标或鼠标点击);
  • time: number — 游戏开始后的时间,考虑暂停(毫秒)。

游戏会话记录

注意

最大的单个会话记录大小为200 KB。

使用 SDK 记录用户的游戏会话(带有时间戳的事件序列)。事件可以是拼图游戏中棋子在棋盘上的移动,也可以是跑酷游戏中键盘或鼠标按键的动作。

在用户输入连续的游戏中,例如跑酷游戏,可以在特定时间间隔内人工生成事件,记录角色状态的指标——坐标、能量水平等。这也可以是游戏中的随机事件——奖励、地震。

游戏中发生的事件作为事务保存。每个事务都有:

  • id —— 事件的唯一标识符;
  • payload —— 事件数据:反映游戏世界本质变化原因的信息(例如角色的新坐标或鼠标按键动作);
  • time —— 游戏开始的时间,包含暂停的修正。

在游戏过程中,通过方法 commit() 保存 payload。这样会形成一个事务列表——游戏会话的时间线 (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() 用于将时间线保存到远程服务器。游戏结束时调用。

保存会话时设置 meta1meta2meta3 的值。至少必须定义一个 meta 参数

使用示例

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

使用会话

要选择如何处理加载的对手会话,请在方法 init() 中传递所需的 isEventBased 标志值:

  • true —— 通过事件处理;
  • false —— 自行处理。

客户端通过 ysdk.on() 订阅事件 multiplayer-sessions-transactionmultiplayer-sessions-finish,而 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);

  // 实现使用时间轴和播放器数据的机制。
}

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();

备注

技术支持团队将协助您将已完成的游戏发布到 Yandex 游戏平台。关于开发和测试方面的具体问题,其他开发人员将在Discord 频道中进行回答。

如果您遇到 Yandex Games SDK 方面的问题或有其他问题想要咨询,请联系支持部门:

发送电子邮件

会话标识符。

自定义参数 meta1meta2meta3,它们在保存会话时设置。例如,游戏分数或玩家等级。

对手玩家的信息:

  • avatar: string — 用户头像的URL;
  • name: string — 玩家姓名。

描述游戏会话的事件时间轴数组:

  • id: string — 事件的唯一标识符;
  • payload — 事件数据:反映游戏世界变化本质、原因的信息(例如,角色的新坐标或鼠标点击);
  • time: number — 从游戏开始到事件发生的时间(毫秒),考虑了暂停的影响。

事件的唯一标识符。

事件数据:反映游戏世界变化本质、原因的信息(例如,角色的新坐标或鼠标点击)。

从游戏开始到事件发生的时间,考虑了暂停的影响。

上一篇
下一篇