分岐がめちゃ複雑なゲームのシナリオって、どう書いたらいいんだろう。
たとえば、上の画像のような「選択肢を選んで、クリックするとその選択肢先のシナリオにジャンプする」ようなノベルゲームを考えます。
もし自分がシナリオライターだったとして、これをテキストでどのように表現したらよいでしょうか。
分岐がない一本道のテキストならば、そのままテキストを書くだけで特に考えることはありませんが、分岐が増えていけば増えていくほど、テキストに表現することが難しくなっていきます。
特に「特定の条件の時だけセリフが変化する」ことや、「特定のフラグでルートが変化する」などの細かい分岐まで考えるようになると、これをテキスト上で表現することが大変になります。
このような「そこそこ分岐が複雑なノベルゲーム」を2022年2月に公開しました。それが、「サバイバルアドベンチャーゲーム、逃げる僕たちと暗黒の森」です。
このゲームでは、シナリオパートを中野藤右衛門 @tohwemon さんに作成していただきました。実際にシナリオをテキストで書いていくにあたって、「分岐指定とか、合流指示とかってどう書いたらいいだろうか」という問題に直面したのです。
この記事ではこのような「分岐が多くて、複雑なフラグが絡んだアドベンチャーノベルゲーム」のシナリオをいかに効率的に作成できるか試行錯誤してみた、という内容になります。
世の中には、このような分岐が複雑なノベルゲームを制作しているシナリオライターの方がたくさんいるかと思うのですが、調べてみても、あまり良い方法を発見できなかったのです。
しゃあないので、独自に考えてみました。もし本業で良いアイデアあったらこっそり教えてください!頼みましたよ!
・逃げる僕たちと暗黒の森(ブラウザゲームです)
https://hothukurou.com/game/Forest/index.html
シナリオ作成からゲームに反映するまでのフロー
ここで、シナリオを作成してから、それをゲームに反映して遊べるようになるまでのフローをまとめました。シナリオのアイデアを頭の中にイメージしている「シナリオアイデア」から、これをテキストに起こして、ゲームで使用するデータ構造に落とし込んで、実際に遊べるようにするまでの流れです。
今回は、この(1)~(3)の変換を効率化していくことを目指しました。
書き方のルールを決める
頭の中にある「面白いシナリオ」をテキストに落としこむ工程は、シナリオライターが一番力を入れる作業となります。
ここで課題になるのが「シナリオ分岐をどのように表現するか」です。実直に書くとすると、こんな感じで書く方が多いのかなと思います。
※背景を雨の画像にする
※BGMを雨のBGMにする
雨が降った。どうする。
(1)傘をさす
(2)傘を差さない
(1)傘を差すとき
[以後、傘を差さないときのシナリオを書く]
(2)傘を差さないとき
[傘を差したときのシナリオを書く]
・上記の選択肢から合流
※背景を家の画像にする
[合流後のシナリオを書く]
この書き方では表記が曖昧です。もっと選択肢を増やして複雑にすると破綻する可能性があります。
ここで、分岐やジャンプ命令の書き方などを指示するためのルールを決める必要がでてきます。
このルール決めにあたり大切なこととして、このテキストをどのようにしてプログラムで使えるデータ構造に変換するのか、という点を考える必要がでてきます。
この変換作業を手動で行うのはめんどくさいので、変換プログラムを組んで、自動でテキストデータからデータ構造を生成したいところです。
これらの要望を踏まえて、今回は「独自のイベント命令」を用意することにしました。
早速、このイベント命令のルールを決めていきます。
基本的な方針としては、各テキストにラベルを定義して、ジャンプ命令でテキストをつないでいく方針で書いていくことにしました。
シナリオの各シーンごとにラベル名を決めて、その下に書いたテキストはそのラベルに属するテキストとなります。
わかりやすいように図にしてみました。こんな感じです。
ラベル指定やラベルへジャンプするようなイベント命令は先頭に@をつけています。これは後でシナリオテキストをデータ構造に変換するプログラムを作った時に、イベント命令なのか、テキストなのかを区別するためにつけています。
イベント命令は他にも作りました。文章に関するイベントだけでなく、ゲーム独自の機能である「背景画像を指定した画像に変更する@Img命令」や、「サウンドを変更する@Snd命令」 などを追加していきました。
全部で30命令ぐらい作成しました。多いですね!
テキストに加えてイベント命令を含めてシナリオテキストを作成するのは大変な話になりますが、これで今回のゲームでやりたいあらゆる演出をテキストで表現することができました。
また、並行してこのテキストをデータ構造に変換するコンバータープログラムも作成しました。
この手のプログラムは書きだすまでが面倒だなあと思うものですが、書き方のルールさえ決めてしまえば1日仕事ですんなり書けるものです。
プログラムの中身は「指定フォルダの中にあるシナリオテキストを全部読んで、先頭から一行ずつ読み出す。一文字目が@だったら、イベント命令として、後に続く単語からイベント内容を決定する。そうでなかったらテキスト表示とする。」という書き方になっています。
コンバーターも完成!シナリオテキストの書き方もシナリオライターと共有できた!
これで開発が進むぞ・・・!と思っていましたが、当然ながらこの方法だと次の問題が発生します。
イベント命令多すぎて覚えられないので、入力補完機能を使おう
私もシナリオライターの中野藤右衛門も、本業はふつうのフルタイムサラリーマンです。毎日せっせと仕事をして、帰宅してゲーム制作に取りくんでいます。
数日激務で仕事に没頭した後、さてやるかとゲーム制作を開始すると、当然ながら事前に取り決めしたイベント命令のことはきれいさっぱり頭から抜け落ちてしまっているのです。
これはしゃあない問題です。でも、ここも「入力補完機能」を用いて解決する方法があるのです。
入力補完機能とは、スマホとかでよく見る「書いている途中で、目的の単語を候補表示してくれるヘルプ機能」のことです。
この入力補完機能を自分で設定できるテキストエディタを使って、命令後を入力補完してもらうようにします。
今回はVSCodeというエディタを使用しました。本来はプログラマ御用達のコードエディタなのですが、エディタとしてみてもVSCodeは扱いやすいのがメリットです。
・VSCode
https://azure.microsoft.com/ja-jp/products/visual-studio-code/
このエディタから、ファイル>ユーザー設定>ユーザーズニペットと選択して、
出てくる選択からプレーンテキスト(txt)を選ぶと、「.txtファイルに適用される入力補完機能」を編集することができます。
この入力補完のカスタム機能を用いて、先ほど定義したイベント命令を一通り書いて入力補完できるようにしました。
これを適用すると、今後は.txtを編集するときにこんな感じで入力補完されるようになります。
例えば、@C と打つと、@ChangeRisk 命令と@ChangeHP命令が候補として表示されるようになります。
曖昧にでも覚えていればイベント命令を打てるようになりました。また、イベント命令のスペルミスもなくなったため、作業効率を上げることができました。
さて、ここで作成したシナリオテキストをプログラマーである私の方でデータ構造にコンバートするのですが、その受け渡しに今回はGitを用いることにしました。
シナリオテキスト共有にGitを使う
Gitとは、特定フォルダ内のデータの更新履歴を貯めることができる便利ツールです。
プログラマが主に愛用しています。色々な機能があるので、使い方がわからないうちは頭がくらくらしてしまうことで有名なのですが、慣れれば非常に役立つツールです。
Gitを使うと、前回からの変更点が簡単にわかるようになるので、「間違えて意図しないテキストもいじってしまった!」というミスがなくなります。
例えば、以下の画像は「危険度の数値を変化して、表現も変えよう」という変更の差分を表示したものです。
下記画像の左が変更前、右が変更後です。
「危険度の数値を変化して、表現も変えよう」という意図の変更がきちんと行われていたかをわかりやすく示すことができます。こういった変更点を容易に可視化してくれるツールがGitの魅力の一つです。
シナリオライターの中野藤右衛門は非プログラマですが、理系大学出身なので、今回このGitの採用を前向きに歓迎してくれました。
一から学ぶには敷居が高いことで有名なGitですが、今回は学習コストを下げるためにも、シンプルでわかりやすい機能だけ使っていくことにしました。
なので、この項目はGitの機能の一部だけを、かなり端折って説明していきます。本業エンジニアの方はたくさんの機能を説明したくなると思うのですが、ここはグッとこらえていただけると幸いです。
とりあえず、必要最低限の「現在の構成をセーブする機能と差分を確認する機能」の使い方の説明を行いました。
また、運用方法の話も2点行いました。「Gitにセーブする前に、今回の更新差分を確認して、変な部分を更新していないか確認してね」と「1機能更新するごとにセーブして、更新内容がわかりやすいようにしよう」という使い方の話です。
Gitは、運用方法を守ることではじめて効果がでてくるものなので、上記の二点をしっかり説明しています。まあ、まずは実際に使ってもらって慣れてもらうと一気に理解度が上がっていました。
Gitの更新差分はVSCodeであれば非常にわかりやすく見えます。そういった意味でもVSCodeは非常に使いやすいエディタです。
さて、次にこのGitを複数人で共有する方法を説明しました。
Gitで差分を管理しているデータのことをリポジトリといいます。このリポジトリをサーバー上にアップすることで、複数人で同じGitデータを共有することができます。
複数人でセーブデータを共有できるというイメージです。このリポジトリをサーバーにアップロードできるサービスの一つがGitHubと呼ばれるサービスです。
このGitHubを用いて、チーム全員が同じGitデータを共有することで、複数人で常に最新のデータを共有することができます。
今回はこのGitHubを用いてシナリオライターとシナリオテキストのやり取りを行うことにした訳です。
GitHubを用いると、ページからこんな感じで開発者各々が更新した内容を確認することができます。
更新内容も差分だけ確認できます。もし誤った更新をしてしまっても気づきやすいため、意思疎通のコストをだいぶ減らすことができます。GitHubもまた、慣れれば非常に便利なサービスです。
こうして、シナリオライターが作成した最新のシナリオテキスト GitHub経由で引っ張ってきて、そのデータをコンバートして、生成したデータ構造をそのままゲーム内に搭載して、ゲームを更新する、という一連のゲーム更新フローが完成しました。
このゲームを制作していた頃は22:00以降の帰宅が多かったのですが、どんなに遅くなっても、5分もあれば更新内容を把握してシナリオライターが遊べるような形でゲームをテストプレイできる状態に持っていけるのです。
ちなみにこのゲームはブラウザゲームなので、更新分のコードをサーバーにアップロードするだけで遊べるようになります。
毎日シナリオ更新分をゲームに反映して、その更新通知をシナリオライターに投げる。その後自分の作業を始めるということを毎日行っていた訳です。
この効率化により、シナリオライターはシナリオ制作に全力を注ぎ、プログラマーもシステム制作に時間をかけることができました。
まとめ
シナリオライターと一緒に複雑な分岐やフラグ管理のあるゲーム制作するにあたり、今回工夫した点は以下三点です。
・シナリオテキストの書き方にイベント命令というルールを追加して、簡単にプログラムのデータ構造に変換できるようにした。
・イベント命令を一々覚えなくてもよいように、入力補完機能を使った。
・Gitで差分管理を行い、更新内容が簡単にわかるようになった。最新データの共有も容易になった。
もう少しシナリオライターのシナリオ制作タスクを軽くするならば、「UIから選択肢分岐させたり、各シーンをくっつけたりできるようにする機能」を制作した方が良いとは思ったのですが、さすがにそこまで実装するのは大変だったので今回の内容になりました。
そんなこんなで完成したこのサバイバルアドベンチャーゲーム、気軽に遊べて10分ほどでなんらかの結末にたどり着くと思うので、ぜひぜひ遊んで感想を送ってもらえると嬉しいです。
・逃げる僕たちと暗黒の森