ゲームバランスの調整手法

逆引きゲームプログラミング (GAME DEVELOPER BOOKS)にのっていたのを自分なりにまとめてみました。

代表的なゲームバランスの調整手法

名称 内容 プログラム
ランク法 EASY/NORMAL/HARDなど、難易度を段階別にする 易しい 家庭用ゲームならほとんど
レベル法 ランク法を細かくしたもの 普通 テトリス
AI法 ユーザのレベルに応じて自動調整 難しい ゼビウス

 
ランク法は、オプションで難易度を選択させるアレです。
最近のゲームには、ほとんど付いてますね(´∀`;
 
レベル法は、ランク法の段階をより細かくしたもので、
0〜255段階とか、難易度にかなりの幅を持たせたものです。
落ちゲーなんかに、よく採用されてますね。
 
AI法は、プレイヤーが明確に難易度を指定できるランク法・レベル法と大きく異なります。
プレイヤーのレベルをプログラム側で判断して、適切なレベルを自動的に選択する方法です。
 
まあ、でも難易度調整が、手動か自動であるだけの違いともいえます。
 
余談ですが、タイピングオブザデッドでは16段階の難易度を自動調整しているみたいです(ゲームの話をしよう〈第3集〉 (ファミ通Books)より)
あと、古い話なのですが、ゼビウスも自動的に難易度を調整しているみたいです。
 
そういった難易度の自動調整機能があると、
プレイヤーが自然とハマれる仕組みを作れるので、
できればAI法で実装するといいかもしれませんねー。
 

調整対象

それぞれの実装に移る前に、調整対象となるものをあげておきます。

  • ゲーム速度(敵の速さ・弾の速さetc)※速くなるほど難しくなる
  • 攻撃パターン(敵の弾の種類etc)※攻撃力や命中率を上げると難しくなる
  • 出現パターン(アイテムの出現率を高くする 敵の出現率を高くするetc)

ランク法の実装

ランクを入力として、switch〜case文で、
例えば「敵の出現データ」などを返してやる感じですね。

敵の出現データ* get敵の出現データ(int rank)
{
	switch(rank)
	{
	case EASY:
		return new 易しい敵の出現データ();
	case NORMAL:
		return new 普通の敵の出現データ();
	case HARD:
		return new 難しい敵の出現データ();
	}
}

例は敵出現データオブジェクトを返すという、
strategyパターンで実装をしていますが、
ランクをグローバル変数にして参照する方法のほうが
作りやすいといえば作りやすいかもしれません。
(その分メンテナンスが大変ですが…(´∀`;
 
ただ、難易度の振れ幅がランクという大きな区切りであるため、
微調整を繰り返すためにパラメータをちくちくいじる必要があり、
結構面倒だったりします。
(まあ、それが面白かったりするのですが…(´∀`;
 

レベル法の実装

レベル法だと、入力値の幅が広いので、なんらかの式により、出現データを返します。

敵の出現データ* get敵の出現データ(int level)
{
	return 出現データ式((float)level / MAX_LEVEL);
}

出現データ式は「0〜1.0」の値を受け取り、
それを元に敵の出現データオブジェクトを生成する関数です。
 
式を立てるまでが大変ですが、いったん決まってしまえば、
ランク法のようにパラメータをちくちくいじる必要がなくなるのが強みです。
 

AI法の実装

AI法は、構築が大変、というデメリットがあります。
しかし、いったん構築すると、ランク法やレベル法よりも微調整の手間が削減されます。
 
というのは、たいていAI法でゲームバランスを管理すると、
判断材料や難易度が一元管理されるからです。
(まあ、ランク法やレベル法でもうまく一元管理できるようにすればいいのですが
 
実装方法としては、

  • プレイヤーの状態
  • 敵の状態
  • 進行状況

を監視するようにして、情報を蓄積し、
ある「一定のタイミング」で「プレイヤーのレベルを判断」し、
敵の管理オブジェクトやアイテム管理オブジェクトに、
判断したプレイヤーのレベルを通知するようにします。
 
クラス図で書くと、こんな感じです。

若干Observerパターンっぽい作りです。
 
要は、

  1. PlayerとEnemyManagerをAIObserverが常に監視(参照)して情報を収集します。(撃墜数・被弾など)
  2. そしてAIDataBaseに情報に蓄積します。
  3. そして一定のタイミングでAIDataBaseの情報をAIEvalに渡すと、「こいつはマニアだ!」とか判定してくれます。
  4. で、「こいつはマニアらしいよ」という情報をEnemyManagerに通知する(渡す)と、「じゃあ、弾幕ふやしちゃるか!」とか判定します。

といった仕組みです。
 
 
判断基準は、例えば、

  • 一定時間内の得点率
  • 一定時間内の連射率
  • 一定時間内のミス率
  • 一定時間内のダメージ率
  • 一定時間内の敵の撃破率
  • 一定時間内のアイテム取得率

となります。
 
「一定時間」と、くどく書いていますが、

得点率=一定時間内の総得点/一定時間

のように「平均」を出すのがポイントです。
 
こうすることにより、
平均値があるラインを超えていたらレベルアップ、
というように、基準を一元化した作りにできるからです。