RPGツクールと数学のブログ

RPGツクールと数学についてのブログです。

複雑なモノ作りに立ち向かう気構え

ゲームクリエイターズキャンプ2ndアドベントカレンダー15日目の記事です。

こんなモノが作りたいな、って頭の中で想像できていても、いざ始めるとどんどん複雑になってしまって、結局挫折してしまう……なんてこと、モノ作りをされている方なら何度も経験あるでしょう。大それたこと言える立場ではないですけれど、私もゲーム作り自体は粛々と長くやっているので、何度も失敗しては再挑戦する経験もそれなりにしています。

当たり前のことをそれっぽく言ってるだけかもしれませんが、大概の挫折の原因はとても単純だと思います。複雑だからです。複雑だから、その掴みどころのないモノを作ることが出来ないんでしょう。難しく考えすぎなんだろうと思います。複雑なモノ作りに立ち向かうには、それをいかに単純にできるかが鍵じゃないでしょうか。

f:id:fermiumbay13:20190313222608p:plain
このシダは実は一種類の曲線を縮小して貼り合わせてできている*1


恐らくどんなに複雑なモノも、分けて分けて、分けまくれば、実はとても単純なモノの組み合わせに過ぎなかった、というところまで分けることができるものだと思います。その単純な要素に分けることが難しい気もしますけれど……それでも、掴みどころのない複雑なモノを複雑なまま扱うより、単純になってくれた方がよっぽど扱いやすいと思います。"分かる"とは、"分ける"こと。

ATB(アクティブタイムバトル)を作ってみる

システムを単純化して考える例として、ATB(アクティブタイムバトル)を作ってみます。ATBとは、ゲージがたまったら行動できる例の戦闘システムですね。ファイナルファンタジーで採用されているアレです。特許は切れてるのですが、ATBという名前は商標登録されているので、使うときは名前を考えてくださいね。

RPGツクールMVでも、プラグインの導入でATBを作成出来てしまうので、わざわざゼロから実装する機会は今やないかもしれません。ゼロから作ろうと思うと、割と考えることがいっぱいであることに気づくと思います。

f:id:fermiumbay13:20190313233624p:plain

どこから手を付けたら作れるんでしょうね??

ということで、とにかく単純化していきましょう。戦闘システムを作るので、初めに戦闘の流れをまとめておくといいですね。

全体の流れを整理する

ATBの例に限らず、システムを作る場合は初めにどんなことができるのか、どう進行するのか、を整理しておくと扱いやすくなります。まずは、戦闘の流れを箇条書きして、要素を抜き出してみましょう。

【戦闘の流れ】

① 戦闘に参加しているキャラクターのゲージが上昇する
② ゲージがたまったキャラクターは行動を選択する
③ 選択された通りの行動を行う
④ 誰かのHPが0になったら戦闘不能とする
⑤ 主人公側、敵側、いずれか全員が戦闘不能になったら終了

このように、戦闘の流れを箇条書きした時点で、「ATB」という大きな複雑なくくりになっていたものが、上記の5つの要素に分けられたのです。これが何を意味しているかというと、後はこの①~⑤それぞれについて考えていけば、ATBが出来ちゃうことになるわけです。

全体の流れが整理できたところで、要素の洗い出しをして単純化をしていきましょう。やり方は人それぞれだと思いますが、ここでは静的な構造に着目する方法と、動的な振る舞いに着目する方法で、それぞれ要素を抜き出します。どちらも恐らくシステム屋さんがシステムの設計をするときによく行われるであろう手法です。

静的な構造に着目する

静的な構造に着目して要素を抜き出します。静的な構造とは、どんな役割をもった要素がそのシステムを構成しているか、というものに相当します。これを考えるときは、あまり各々の要素の動きについては考えません。

f:id:fermiumbay13:20190314010110p:plain

ATBの例でいえば、戦闘システムに登場するすべての要素を洗い出す作業に相当します。ここでは主人公と敵はそれぞれ1体ずつに限定して考えましょう。

要素1:HP
・相手から攻撃を受けると減る値
・0以下になるとそのキャラが戦闘不能になる

要素2:ゲージ
・時間経過でたまっていく
・満タンになるとそのキャラが行動可能になる

要素3:主人公
・プレイヤーが操作する対象のキャラクターで、HPを持つ
・行動可能になったら、行動を選択し、敵に攻撃する
・戦闘不能になったら、ゲームオーバー

要素4:敵
・プレイヤーと戦う相手で、HPを持つ
・行動可能になったら、その敵の技が自動で選ばれて行動する
・戦闘不能になったら、プレイヤーの勝ち

このように要素を洗い出しておくと、各要素の関係がはっきりするので、扱いやすくなります。ゲージをためる部分を作ろうと思ったら、ゲージのことだけ考えればよくなりますからね。

静的な構造を図にしてまとめるときにはクラス図が便利です。詳細は割愛しますが、各々の要素がどういう特徴をもっていて、静的にどう繋がりをもっているか、をまとめたものになります。

f:id:fermiumbay13:20190314012535p:plain

クラス図のイメージ(この例はだいぶんカジュアルなので、きちんと描く場合は描き方を別途確認してくださいね)

動的な振る舞いに着目する

次に動的な振る舞いを考えます。動的な振る舞いとは、コレがこうなってこうなって、こうなる、という、要素ごとの動きのことを指します。このATBの例でいえば、各々の要素が戦闘中にどう動くかに相当しますね。

先ほど洗い出した要素に対して、それぞれ動きを整理してみましょう。主人公始点で考えて見ます。

① 主人公のゲージは時間経過に伴い上昇する
② ゲージが満タンになったら主人公を行動可能にする
③ 主人公は行動可能になったら行動を選択し、敵を攻撃する
④ 攻撃された敵のHPを減少する
⑤ 敵のHPが0以下になったら敵を戦闘不能にしてプレイヤーの勝ち 

動的な振る舞いを図にしてまとめるときはシーケンス図が便利です。こちらも詳細は割愛しますが、シーケンス図は、各々の要素がこうなってこうなる、このタイミングでこういう行動をする、というのをまとめるのに便利な図です。

f:id:fermiumbay13:20190314013603p:plain

主人公視点のシーケンス図のイメージ(この例もカジュアルです)

ここまで単純化できたら実装できるはず

要素を抜き出して、各々の要素がどんなことができて、いつ何をするのか、これまでの洗い出し作業によって明らかになったと思います。ここまで単純化できたら、各々の機能は小さいはずなので、そんなに苦も無く実装していけると思います。

まずは静的な構造の実装を確認していきます:

要素1:HP
・HPは値なので、変数で管理する
・相手から攻撃を受けた値だけ値を減らす
・0以下の場合、対応するキャラを戦闘不能にする

要素2:ゲージ
・ゲージの長さは値なので、変数で管理する
・時間が経ったらそのぶん値を増やす
・値が満タンになるとそのキャラを行動可能にする

要素3:主人公
・行動可能になったら、敵に攻撃する
・戦闘不能になったら、ゲームオーバー

要素4:敵
・行動可能になったら、プレイヤーに攻撃する
・戦闘不能になったら、プレイヤーの勝ち

この時点でどうしても実装に悩む箇所があるなら、それだけを検索なり、質問なり、すればよいことにもなるでしょう。単純化できているので、調べやすくも聞きやすくもなっているものと思います。例えばゲージの管理方法で悩まれたなら、ゲージとはこういうモノなのですが、どう管理すればいいでしょうか、など質問し、変数で管理するのがいいですね、などの回答が得られれば、変数を採用すれば良いのです。

これらを動的な振る舞いに当てはめてみます。

① 主人公のゲージ(変数)を上昇、満タンになるまで繰り返し
② ゲージが満タン(例えば100)になったら主人公を行動可能にし、ゲージを0に戻す
③ 主人公は行動可能になったら行動を選択し、敵を攻撃する
④ 攻撃された敵のHP(変数)を減少(例えば10~20の乱数で減らす)、HPが残っていたら①に戻る
⑤ 敵のHPが0以下になったら敵を戦闘不能にしてプレイヤーの勝ち 

実装方法が確立したら、あとはイベント命令に起こすだけです。とりあえず主人公の番だけですが、こんな感じにでもなるでしょう。

◆ループ
 ◆注釈:① ゲージ上昇
 ◆変数の操作:#0002 主人公のゲージ += 1
 ◆注釈:② ゲージが満タンになって主人公が行動可能に
 ◆条件分岐:主人公のゲージ ≥ 100
  ◆変数の操作:#0002 主人公のゲージ = 0
  ◆注釈:③ 行動選択、敵に攻撃
  ◆文章:なし, ウィンドウ, 下
  :  :主人公の番だよ
  ◆選択肢の表示:攻撃, 何もしない (ウィンドウ, 右, #1, #2)
  :攻撃のとき
   ◆注釈:④ 敵にダメージ
   ◆変数の操作:#0003 敵のHP -= 乱数 10..20
   ◆注釈:⑤ 敵が戦闘不能
   ◆条件分岐:敵のHP ≤ 0
    ◆文章:なし, ウィンドウ, 下
    :  :敵がやられたから主人公の勝ち!!
    ◆ループの中断
    ◆
   :分岐終了
   ◆
  :何もしないのとき
   ◆
  :分岐終了
  ◆
 :分岐終了
 ◆
:以上繰り返し

後はこれをベースにして、ゲージや主人公の絵を表示したり、コマンドを増やしてみたり、といったことをしていけばいいことになります。

全体として見ると色々やってそうですけれど、単純化した各要素の小さな単位で考えたので、あんまり複雑なモノを作った感じがしないのではないでしょうか。

いや、こんなもん作るのに何も困らんわ!と思われるかもしれないですけど、もっともっと大きくて複雑なシステムになっても同じ考え方で、単純化して、各要素の小さな機能を実装していく、という方法は適用できると思うので、同様にして十分何でも作っていけると思います。

せっかく面白いシステムを考えても、実装出来ないととてももったいないので、この記事で紹介したような考え方でも、参考いただければありがたいです。

*1:バーンズリーのシダというフラクタル図形です