Join と Leave

このページのサンプルコードをダウンロード

# Join

各プレイヤーには「join しているか否か」という二値の状態が存在します。これは実行環境が規定する値です。「join しているプレイヤー」が何を意味するかは、実行環境によって定まります。

あるプレイヤーが join 状態になる時、 g.game.onJoin が fire され g.JoinEvent が与えられます。同様に join 状態でなくなる時、 g.game.onLeave が fire され g.LeaveEvent が与えられます。

元々はその名の通り「ゲームに参加する」動作を表現するために作られた機能ですが、 歴史的経緯から、現在は実行環境が規定する「特殊なプレイヤー」を通知するものになっています。

特に ニコニコ生放送上で実行する場合に、配信者と視聴者を区別するために利用できます

joinするプレイヤー いつjoin状態になるか いつjoin状態でなくなるか
ニコニコ生放送
(mode: "multi_admission")
配信者 ゲーム開始直後 なし(joinしたまま)

次のコードは、最後に join したプレイヤーを記憶して参照する例です。

let lastJoinedPlayerId = null;

g.game.onJoin.add(ev => {
  lastJoinedPlayerId = ev.player.id;
});

scene.onPointDownCapture.add(ev => {
  if (ev.player.id === lastJoinedPlayerId) {
    // ニコニコ生放送上で動かす場合、イベントを生成した(=画面を押下した)のが「配信者」である時のみ実行される
    // ...
  }

  if (g.game.selfId === lastJoinedPlayerId) {
    // ニコニコ生放送上で動かす場合、この実行環境(インスタンス)が「配信者」のものである時のみ実行される
    // ...
  }
});

なお g.game.selfId は、今そのゲームを実行している環境(インスタンス)のプレイヤー ID です。このコード例のように、あるイベントの生成元が自分(このインスタンス自身)かどうかを判断したい時に利用できます。

g.game.onJoing.game.onLeave の動作確認は akashic serve コマンドでも行うことができます。

serve

画面上側、ツールバー上の「Join Me」ボタンを押すと、そのウィンドウ(インスタンス)のプレイヤーが join します (g.game.onJoin が fire されます)。 join 済みの場合は「Leave Me」ボタンに切り替わり、 g.game.onLeave を fire させることができます。

ここでは g.game.onJoin の説明のため扱っていませんが、Akashic Engine v3 では g.game.joinedPlayerIds を利用することもできます。 g.game.joinedPlayerIds は、その ゲームプレイ中に join した (leave していない) すべてのプレイヤー ID を保持する配列 です。

そのため lastJoindPlayerId を自力で求めずとも、次のように書くことができます。

if (g.game.joinedPlayerIds.includes(ev.palyer.id)) {
  // ニコニコ生放送上で動かす場合、イベントを生成した(=画面を押下した)のが「配信者」である時のみ実行される
  // ...
}

# g.game.selfId とローカル処理

g.game.selfId は「プレイヤーごとに異なる値」です。そのため これを参照する条件分岐内の処理は ローカル処理 になる ことに注意してください。

先ほどのコードのこの部分がこれに該当します。

if (g.game.selfId === lastJoinedPlayerId) {
  // ニコニコ生放送上で動かす場合、この実行環境(インスタンス)が「配信者」のものである時のみ実行される
  // ...
}

この if 文のブロックは、明らかにプレイヤーによって実行されるかどうかが異なります。 そのためローカルイベントに対する処理と同じく、「プレイヤー間で間接的に共有されている実行状態」を破壊してはいけません。 たとえば g.Game#random を利用したり、非ローカルなエンティティを生成・操作すると、他プレイヤーと実行状態がずれてしまい、マルチプレイが破綻します。

詳細は ローカル処理とその制限 を参照してください。

なお、同じ先ほどのコードでも、こちらはローカル処理になりません (通常のシーンの場合)。

if (ev.player.id === lastJoinedPlayerId) {
  // ニコニコ生放送上で動かす場合、イベントを生成した(=画面を押下した)のが「配信者」である時のみ実行される
  // ...
}

イベント ev は (ローディングシーンなどでない通常のシーンの場合) 全プレイヤーが共通して受け取る値です。 また lastJoinedPlayerIdg.game.onJoin という「全プレイヤーが共通して受け取る通知」から求められているので、プレイヤーに依存しません。 そのためこの条件分岐の中は、全プレイヤーが同じイベントを受け取った時には同じように実行されるはずです。

このように、ある条件分岐のブロックがローカル処理の制限を受けるかどうかは、参照する値がプレイヤー依存かどうかによって決まります。

# ニコ生ゲーム用動作確認

akashic serve コマンドは、 --target-service (省略名 -s) オプションに nicolive を指定して起動すると、ニコ生ゲームの開発に便利な振る舞いになります。 この状態では「Join Me」ボタンが無効になり、最初に開いたウィンドウのプレイヤーだけが必ず join します (配信者役になります) 。 そのため都度ボタンを押す手間が省けます。

akashic serve --target-service nicolive

その他、ニコニコ生放送に関する内容は、 開発者向けガイドニコニコ生放送で遊べるゲームの作成 を参照してください。