マルチプレイゲームを作ろう4 実際にゲームを考えて作ろう
このページの情報は古くなっています。最新の情報は https://akashic-games.github.io/shin-ichiba/ を参照してください。
前回までの連載で、Akashic Engine + マルチプレイ なゲームを作るための大雑把な知識を導入し終わりました。
最後に、いままでのおさらいや考え方を軽く流した後に、こちらで用意したサンプルゲームの紹介をしていこうと思います。
今回は今までの記事の総決算であるため、今までの連載を1項目につき一行でおさらいします。
- マルチプレイゲームとはどういうものか
- 他人が同じ世界に存在し、共有物やお互いに干渉しあうゲーム
- 他人と自分で違う状態を持つ方法
- ローカル処理によって自分のPCだけで発生する処理、を記述できます
- 自分の操作を他人へ伝える方法
- raiseEventによって、任意の情報を全員に送信することができます
- ニコ生上で動作させるためのtips
- ゲーム起動直後のJoin処理によって、放送者を識別することができます
かなりの超特急にも感じますが、仕組みの解説は殆ど終わっています。
今回紹介するサンプルゲームも、今まで連載に出て来た以上のことはしていません。
実際のゲームの中身は皆さんに考えていただくとして、以上の知識があれば理論上はマルチプレイゲームが作れます。
したがって以下では、技術の話というよりはサンプルゲームを紹介しつつ、どのような流れで作り、何を気をつけたか、といった大まかな流れの部分を説明していこうと思います。
一番最初の記事に遡って、どんなゲームを作るか考えます。こういう時のコツは、目標や条件など定義して自らに制約を課すことです。
今回は以下の制約を設定しました。
- ニコ生上で投稿ゲームとして動作させること(運営だけが使える機能みたいなのは使わない)
- PC、スマホ両方で遊べること
- スマホ対応、という点からキーボードとマウスに依存しないこと
- PC対応、という点からマルチタッチに依存しないこと
- 以上より、指一本で遊べ、精密なタッチを要求しないこと
- 小さいマス目を正確にタッチする、みたいなのはスマホではキツイ
- 綺麗な直線を素早く書く、みたいなのはマウスではキツイ
- 放送者を含む参加者全員のガチンコ勝負で、最後に一人だけ勝者が決まること
- 画面上に他人が存在すること
- 複雑なルールを要求しないこと
こんな感じで設定しました。
最近のニコ生ではタワーが流行っています。少し前はつりっくまやだるまさんがホットでしたね。
タワーは協力ゲーム、だるまさんは放送者vs他全員、つりっくまは個人戦だけど他人の様子がよくわからない、という特徴を持っていました。
今回はそれのいずれとも性質の異なるゲームを作りたくて前述の制約となりました。
岩を避けながらジャンプし、少しずつ右へ進んでいくゲームを作りました。
最大30人まで参加することができます。見た目はなんともですが
- 放送者をゲームマスターとした参加、募集締め切り
- 参加者全員で同期したゲーム進行
- 自分のジャンプを全員に通知し同期させる
といった、マルチプレイゲームに必要な要素はだいたい入っていると思います。
ソースコード一式は以下で入手できます。
https://github.com/akashic-contents/jumper-game
- ゲームが起動されると誰かのjoinを一回だけ待つ
- joinして来た人をゲームマスターとして設定
- タイトル画面で参加者待ち受け開始
- ゲームマスターが適当なタイミングでゲーム開始
- ゲーム画面で遊ぶ
- 終了条件を満たしたら終わり
- 3に戻る
これを繰り返します。以下で個別に解説していきます。ゲームマスターやJoinについては第3回の記事が理解に役立つでしょう。
ゲーム起動直後のコードがこんな感じです。
function onJoin(e) {
// e.player.idを使って初期化処理
}
g.game.join.addOnce((e) => {
onJoin(e);
});
// joinを待ち受ける仮のシーン
const dummyScene = new g.Scene({game: g.game});
dummyScene.update.add(() => {
});
g.game.pushScene(new g.Scene({game: g.game}));
Akashic Engineの仕組み上でのJoinを待ちます。ニコ生ではゲーム起動時に放送者のみがJoinする、という仕組みになっていますので実際にはほぼ一瞬かと思います。
タイトル画面の中身は解説記事第三回の中身ほぼそのままです。
ボタンを二つ初期化し、ゲームマスターには参加締め切りボタン、それ以外の人には参加ボタンを表示しています。
それぞれのボタンはローカルエンティティとなっていて
- 開始ボタン:closeメッセージを全員に送り、募集を終了する
- 参加ボタン:joinメッセージを送り、募集に参加する
という機能を持ちます。ここでいうjoinはAkashic EngineのJoinとは関係ない、このゲーム独自の処理です。
ゲームが開始されると、もし参加していればボタンが二つ表示され、自分のキャラ(Jumper)が赤くハイライトされます。
ここで重要なのは、何がローカルで何がグローバルなのかを考えることです。
Akashic Engineでは特筆しない限りグローバルとなるので、この画面に存在するもののほとんどはグローバルであり、ローカルなものを抽出したほうが早いでしょう。
と言いつつ、ローカルなものは殆どありません。
敵の配置やラウンド進行、残り人数や順位といった、ほぼ全ての情報は同期してほしいためグローバルになっています。
ローカルな分岐で破壊しないことに気をつけて書くだけで、全ての操作が同期するのは結構すごいことです。Akashic Engineの強みです。
一応以下に、意識してローカルエンティティを書いた部分をあげておきます。
まず、左下と右下にあるボタンは操作用のもので、これを押すとJumperがジャンプしたり、挨拶したりします。 自分がジャンプボタンを押した時、自分のJumperだけがジャンプしなければなりません。
これを実現する方法は二つあります。
- ボタンが押された時の処理で誰が押したかを判定し、そのキャラだけをジャンプさせる
- ボタンをローカルエンティティとして作り、メッセージを送信してそのメッセージでジャンプさせる
どちらでも実現できます。1のほうが処理が簡単なのですが追加条件として
a. ジャンプした後はしばらくボタンが押せない
b. ジャンプできない場合、ボタンがグレーになる
をつけると話が変わってきます。aだけであればまだ1でも大丈夫でしたが、ボタンそのものの状態を各々変えるにはボタンをローカルエンティティにする必要があります。
そうするとボタンが押された時の処理にはグローバルなものが書けないため、2の手法を取る必要があります。挨拶ボタンに関しても同様です。
Jumperの画像もローカルエンティティです。
Jumperの位置、生死、ジャンプしているかどうかなどといった情報は全てグローバルなものですが、自分のJumperは強調表示されてほしいため、Spriteはローカルエンティティで作ります。
実際にゲームを作っていくとすぐにわかることなのですが、raiseEventを使わなければならないシーンはかなり少ないです。
状態は何もしなくても他人と同期するというAkashic Engineの特徴があるためです。
同期していないもの、つまり他人が知り得ない情報が同期状態にあるものに影響を及ぼすとき初めて、raiseEventの出番になります。
大体において、これは誰かがローカルなエンティティを操作した時が該当します。
自分だけの操作は他の人は知り得ないので、操作した結果を通知する必要があるわけですね。
今回は今までのおさらいを軽くしつつ、いままでのまとめとして作ったマルチプレイゲームを掲載しました。
マルチプレイゲームの作成に基本的な知識は解説し終わりましたので、ここで一旦連載企画は一区切りとなります。
ニコ生上でマルチプレイゲームを作るという試みは一見荒唐無稽ですが、ニコ生での新しい遊び方の一つとして今後も進めていきたいと考えています。
現時点でも、ニコ生上でゲームを動作させると以下のようなメリットがあります。
- サーバーを用意せず公開できる(生放送にきてもらう必要がありますが)
- ログイン機構がいらない(ニコニコにログインしないとゲームが操作できない)
- タイムシフトに対応する(Akashic Engineの機能でプレー内容が保存される)
まだまだ機能が少なかったり、解説できていない機能もあったりしますが、この記事が少しでも新市場ユーザー投稿ゲームの助けになれば幸いです。