#目的
RPGの「生物クラス」を設計しているが、戦闘に関して「どの部分がどのクラスの役割になるのか」を切り分けたい。
[課題]
・1対多の戦闘で、生物が「行動の対象」をどう管理すべきか
・1ターンの行動後、行動結果をどう処理するか
※ これだけだと分かりづらいので、具体例は後述。
#結論
結果を先に書くと「戦闘マネージャクラス」を作り、戦闘に関する一切を管理させるのがスムーズな設計になりそうだ。
→ じつはこれまでに書いたコードでは、「生物クラスが、攻撃対象の情報を受けてあれこれする」という設計になっており、見直しをした。
⇒ 旧設計では「生物」が「他の戦闘参加者たち」を把握しているべきだ、と考えたが、新設計では「戦闘管理者が、戦闘参加者たちを把握」することにした。(そのほうが自然)
#擬似コード
従来タイプでは
var Creature = cc.Class.extend({
HP:1, // ヒットポイント
AI:null, // AI(性格、行動に影響)
…(中略)
hurt:function(dmg){
this.HP -= dmg;
},
magic:function(magic, target){
this.MP -= getMP(magic); // MP減らす
target.hurt(メラ); // ダメージ受ける
}
});
var Slime = new Creature(引数);
var Magician = new Creature(引数);
Magicial.magic(メラ, Slime);
といった具合に、行動者と、被害者のことをCreatureクラスの処理内(たとえばmagicメソッド内)で、一緒くたに定義していた。
これだと、行動者が「戦闘に参加している敵全員を把握」している必要があったのだ。そこで、もう少し切り分けをして、 戦闘管理者クラスを作ることとした。
var BattleManager = cc.Class.extend({
entrants:[], // 参加者(Creatureの配列)
…(中略)
ctor:function(参加者){
this.entrants[]=参加者たち;
}
decideTurn:function(){ // 行動順の決定
参加者数ループ、素早さや運の計算
},
decideAction:function(who){ // 行動の決定
AI = who.getAI(); // 行為者のAI(性格)取得
ret = AI.getAction(状況); // AIに、状況に応じた行為を決めさせる
return ret;
},
doAction:function(who, action){ // 行動の実行
select case(action){
case 呪文:
呪文のMPチェック→ 呪文唱える
呪文の種類、攻撃対象(単体か複数かなど)
for(i=0; i<対象の数; i++){
whoとターゲットに対し、それぞれ呪文の結果を実施
(ここ以下を関数化するか?)
・ダメージ計算(自分と対象の属性による)
※ 属性による増減、炎反射・半減などの耐性判定も。
場合によっては行為者自身も損害受けるなど
・結果をメッセージ表示・アニメーションなど
・行為者や被害者が死亡した場合(参加者配列から抜き取る等)
}
case 物理攻撃:
※ 呪文の場合とおおむね同様
}
}
});