JA

チュートリアル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://…)で、使うサーバーを指定します。