小学生の頃パワポでゲームを作った話
夏なのでポエムを書きます。
はじめに
タイトルの通り、小学生の頃パワポ(P○werP○int 97)でゲームを作ってました。何を言っているのか分からないという人のために、当時作っていたものをG○○gle スライドで再現してみました。
ここをクリックで開始。PCでもスマホでも動きます。多分。
コマンドを選択することによってゲームを進める、いわゆる「アドベンチャーゲーム」というやつです。パワポやG○○gle スライドではオブジェクトに「特定のスライドへのリンク」を貼ることができるため、「『はなす』ボタンが押されればスライド5にジャンプ」「『いどう』ボタンが押されればスライド8にジャンプ」といったことができます。これによりゲームブックのようなものを作ることができます。
と、ここまでの内容は「パワポ ゲーム」などで検索したらすぐに見つかります。しかし、より込み入った内容を書いているページが見つからなかったため、私の小学生当時の研究成果をここにまとめ、供養しようと思います。
基本編
■分岐
スライドでゲームを作る上で基本となるのはリンクによる分岐です。押したボタンによって異なるスライドにジャンプします。状態遷移図を使ってこれを表してみましょう。状態はスライド、遷移はリンクに対応します。つまり下の図は3枚のスライドを表しています。
■状態数の爆発
何も考えずに分岐を多用すると、あっという間に状態数、つまりスライドの数が爆発します。2分岐がN回あると単純計算で2^(N+1)-1枚のスライドが必要になります。例えば2分岐が1回だと3枚、2回だと7枚。2分岐が7回もあれば255枚ものスライドが必要になります。これだけのスライドを作るのは避けたいところです。
■枝刈り
状態数の爆発を防ぐ一番簡単な方法として「間違った選択肢を選んだら即ゲームオーバーにする」という手があります。2分岐がN回あり間違った選択肢を選ぶと即ゲームオーバーにすると必要なスライドは2(N+1)-1枚。指数関数が線形関数になりました。2分岐が7回あっても必要なスライドはたったの15枚。ただ、すべてをこの方式にするとゲームとしていささか問題があるので通常の分岐と組み合わせるのがよいでしょう。
■合流
状態数の爆発を防ぐ別の方法として「分岐したスライドを再び合流させる」という手があります。選択肢によって異なるスライドにジャンプさせますが、その後に共通のスライドに(無条件で)ジャンプさせます。下の図にラベルのない矢印が出てきますが、これはボタンなどではなく画面の任意の場所をクリックすることで遷移することを表しています。細かい話を書くと、スライド全体(画面全体)にリンクを貼ることにより、クリックしたときに次のスライドではなく特定のスライドにジャンプさせることができます。
■ループ
合流の亜種としてスライドをループさせるという手も使えます。これは「何度話しかけても同じことを繰り返す村人」を実現するためのテクニックです。これを応用することで「鍵を持っていないと先に進めない」といった仕組も実現できます。
応用編
■論理変数
ループのところで少し触れた「鍵を持っていないと先に進めない」といった仕様を実現するためには「鍵の有無」を表す論理変数を使いたいところですが、スライドではそんな便利なものは使えません。変数の値によって状態、つまりスライドを分けることになります。
上の例では「玄関」で「植木鉢を調べる」か「ドアを開ける」のどちらかを選ぶのですが、すでに鍵を持っているかどうかで動作が変わります。そのため「玄関」のスライドは2枚必要なわけです。もし「鍵Aと鍵Bの2つの鍵を持っていないと先に進めない」という仕様にしたい場合、それぞれの鍵の有無が4パターンあるため、玄関のスライドが4枚必要になります。ただし「鍵Aを先に見つけないと鍵Bは見つからない」という仕様にすると「鍵Bはあるけど鍵Aがない」というパターンが省けるため必要なスライドは3枚に減ります。また、複数の論理変数が「同時に」必要な場合は必要な状態数が指数関数的に増えますが、ある論理変数による分岐が完全に終わった後に別の論理変数を使うのであれば、古い論理変数の値を忘れて良いので必要な状態数は増えません。状態数を爆発させないためにはゲームの仕様を工夫するのが大事になります。
■整数変数
「村人に3回話しかけると台詞が変わる」という仕様を実現するためには「話しかけた回数」を表す整数変数を使いたいところですが、もちろんそんな便利なものは使えません。論理変数と同様に変数の値ごとにスライドを作る必要があります。
この場合、変数は0~2の3通りの値を取るのでスライドが3枚必要になります。0~100までの値を取りうる変数のことなど考えたくもありません。基本的に取りうる値の範囲が広い整数変数は使わないほうが無難です。状態数が増えると心が折れます。
■忘却による節約
「2回連続で4択の選択肢を正しく選べばゲームクリア」という仕様を考えてみましょう。例えば、まず「北館」「東館」「南館」「西館」のなかから1つを選び、次に「1階」「2階」「3階」「4階」のなかから1つを選ぶ。「北館」「4階」の組み合わせを選べばゲームクリア。それ以外の組み合わせではゲームオーバーとしましょう。単純な分岐で作ると1回目の分岐の後に4つの状態が必要になります。
1回目の選択肢を間違えた時点で即ゲームオーバーにしていいのなら状態数は減りますが、あくまでも2回目の選択肢の後にゲームオーバーにしたいとしましょう。もし「東館」「南館」「西館」の3つを選んだときに違いがない、つまり何を選んだのか忘れていいのであれば1回目の選択肢は実質的に「北館」と「その他」の2択になるため、状態数を減らすことができます。
この節約をするためにはゲーム自体の工夫が必要になります。例えば画面上に今いる場所を表示してはいけません。絵やセリフなどにも注意が必要です。どの選択肢が選ばれたか忘却していいようにゲームを設計する必要があります。しかしながら、選択肢の段数が増えるとこの節約の効果は著しいので、スライドで複雑なゲームを作るときにはぜひとも活用したいテクニックです。
実践編
以上のテクニックを使って作ったのが冒頭に載せたゲームです。念の為もう一度貼っておきます。
さて、このゲームですが基本的に「神社」「公園」「駅」の三箇所を行き来します。ループ構造になっており、テキトーに行き来するだけではゲームは進行しません。
ゲームは「ラガールカードを取得すること」と「ラガールカードを持って駅に行く」ことで進行します。これは2つの論理変数で管理されると考えられますし、0~2の値を取る整数変数で管理されると考えても構いません。
ゲーム本編は以上の状態によって表現されますが、これ以外に重要な要素として「パスワード」というものがあります。ここで言うパスワードとは中断したゲームを再開するために入力する文字列です。ドラクエの「復活の呪文」が有名ですね。データを保存するすべを持たないスライドによるゲームとの相性はバッチリです。今回は「タイトル画面でパスワードを入力できる」「神社で現在のパスワードを確認できる」「パスワードは4桁の数字」という仕様にしました。4桁の数字です。0000~9999までの1万通りあります。これを単純な分岐で実装するのは実質不可能です。そこで役に立つのが「忘却による節約」のテクニックです。入力されている数字を覚える代わりに「(少なくても今の所)正しいパスワード」なのか「(すでに)間違っているパスワード」なのかを覚えます。今回は正しいパスワードが「1192」「1185」「1180」の3種類あります(それぞれs=0,1,2に対応)。1桁目が「1」以外であればその時点で間違いであり、残り3桁が何を押されたかを気にする必要はありません。つまり1桁目は「1」と「その他」の実質2分岐です。2桁目も同様。3桁目は「9」「8」「その他」の3分岐。一度でも間違えればそれ以降は分岐せず4桁目が押されるのを待つだけです。
これにより4桁のパスワードをごく少数の状態で表現できます。実際に入力された数を覚えているわけではないので、画面に入力された数を出すことはできません。また「1文字戻る」機能を実装すると必要な状態の数が増えてしまうため、後戻りはできないようにしました。
1文字戻れそうなボタンは見掛け倒しです。タイトルまで戻ります。
上の状態遷移図ではゲーム本編が9状態、パスワードが8状態ありますが、図中からは省略したスライドやセリフのためのスライドなどがあるため、実際にはゲーム本編のスライドが32枚、パスワードのためのスライドが9枚、合計41枚となっています。これくらいの枚数なら少し気合いを入れれば作れますね。
おわりに
以上が私が小学生だったときに活用したテクニックです。当時は状態遷移図なんてものは知らず、必要となるスライドの枚数も計算できませんでしたが、頭の中で「なんとなく」いろいろな手法を発見しました。特にパスワードを実装する方法を思いついたときは一人で興奮しました。しかし、それを誰かに伝えることもなければ、その発想が後に役立つこともありませんでした。大学でオートマトンを学んだときや、Common Lispで文字列比較のために決定性オートマトンを生成するマクロを書いたときも、このパスワードのことを思い出すことすらありませんでした。むしろ、この記事を書くために状態遷移図を描いて、当時自分が「パスワードを受理するオートマトン」を作っていたことを今になって気づきました。おそらく今後も活かされないであろう知見をここに記し、供養したいと思います。


コメント