教程 7 — 在线多人游戏
JumPHP 通过中继服务器(WebSocket)把玩家连接起来:在线代码在桌面和浏览器中完全相同。游戏 Pong 就是完整的示例(src/Scene/PlayScene.php)。
大厅
$this->scenes()->switchTo(LobbyScene::class, [
'next' => PlayScene::class, // 玩家到齐后进入的游戏场景
'nextParams' => ['mode' => 'online'],
'back' => TitleScene::class,
'players' => 2,
]);
大厅可以创建房间(一个可以分享的 4 位字母代码)、加入房间,或者自动匹配对手。随后它会带着 ['online' => true, 'net' => NetSession, 'host' => bool, 'peer' => int] 打开游戏场景。
消息
$net = $params['net'];
$net->removeAllListeners();
$net->on('message', fn (int $from, int $type, string $payload) => $this->receive($from, $type, $payload));
$net->on('peerLeave', fn (int $peer) => $this->scenes()->switchTo(TitleScene::class));
$net->send(self::MSG_STATE, pack('gg', $this->x, $this->y), reliable: false); // 频繁发送:允许丢包
$net->sendJson(self::MSG_EVENT, ['goal' => 1]); // 偶尔发送:保证送达
推荐的架构
- 由主机裁决:主机负责模拟对局、计分,并每秒约 20 次发送游戏状态;
- 其他玩家每秒约 30 次发送自己的操作;
- 其他玩家的对象带有一点平滑的延迟来绘制:使用
SnapshotBuffer(先push($this->engine->time(), $state),再sample($this->engine->time()))。
中继服务器可以在你自己的电脑上用 bin/jumphp relay up 启动;游戏通过 game.yaml 中的 net_url
(或页面地址中的 ?net=wss://…)指定自己使用的服务器。