状態異常の演出
今回は「状態異常」にかかった際の動的な変更、演出を実装していきます。
どく状態になれば、メッセージに合わせて「どく」を表記、まひ状態になれば、メッセージに合わせて「まひ」をセットするという単純なものです。
返り値の変更
それではまず、状態異常をセットしてメッセージを生成しているsetSaに修正をかけていきましょう。
ポケモンクラス用セットトレイト(/Traits/Class/Pokemon/ClassPokemonSetTrait.php)
/**
* 状態異常をセットする
* @param string $class
* @param integer $turn|0
* @return array
*/
public function setSa($class, $turn=0)
{
// ひんしをセット
if($class === 'SaFainting'){
$this->sa = [$class => $turn];
// ランク・状態変化・バトルダメージをリセット
$this->releaseBattleStatsAll();
// 進化フラグがtureになっていればfalseに変更
if($this->evolve_flg){
$this->evolve_flg = false;
}
// メッセージの返却
return [
'message' => $this->getPrefixName().'は倒れた'
];
}
// セットできる状態異常一覧
$sa_list = [
'SaBurn', 'SaFreeze', 'SaParalysis', 'SaPoison', 'SaBadPoison', 'SaSleep',
];
// クラスチェック
if(!in_array($class, $sa_list, true) || !class_exists($class)){
// 不正なクラス
return [
'message' => '指定された状態異常は存在しません'
];
}
// 状態異常にかかっていない場合
if(empty($this->sa)){
$sa = new $class;
// 状態異常をセット
$this->sa[$class] = $turn;
return [
'message' => $sa->getSickedMessage($this->getPrefixName()),
'sa' => $class
];
}
if(isset($this->sa[$class])){
$sa = new $class;
// 既に同じ状態異常にかかっている
return [
'message' => $sa->getSickedAlreadyMessage($this->getPrefixName())
];
}
return [
'message' => 'しかし上手く決まらなかった'
];
}
今まではメッセージをそのまま返却していましたが、それでは「成功」か「失敗」かの判断が付きません。なので、配列にしてメッセージには「message」というキー、状態異常にかかった際は「sa」というキーにクラス名を格納して返却しています。
メッセージとレスポンスの格納
次に、状態異常メッセージ・レスポンスの受け取りから格納までの流れです。
今まではメッセージだけを返却していたので、技のeffectsメソッド内でメッセージのセットを行なっていましたが、そうなるとそれぞれの技で分岐を作る必要があります。それは保守性も悪く作業効率もよく有りませんので、攻撃トレイト内で共通処理ができるように、effectsではsetSaの返り値をそのまま返却します。
状態異常をセットする技の例として「どくのこな」を見てみましょう。
どくのこな(/Classes/Move/MovePoisonPowder.php)
/**
* 追加効果
*
* @param array $args
* @return array
*/
public function effects(...$args)
{
/**
* @param Pokemon $atk 攻撃ポケモン
* @param Pokemon $def 防御ポケモン
*/
list($atk, $def) = $args;
// 相手をどく状態にする
return $def->setSa('SaPoison');
}
これで、返り値をそのままトレイトへ返却することができるようになりました。
では、受取先のトレイトに分岐を追加しましょう。
攻撃用トレイト(/Traits/Service/Battle/ServiceBattleAttackTrait.php)
// attackSuccessメソッド内
// 追加効果(相手にHPが残っていれば)
if($def_pokemon->getRemainingHp()){
// 追加効果
$effects = $this->effectMove($atk_pokemon, $def_pokemon, $move);
// バトル終了
if(isset($effects['end'])){
$this->setMessage($effects['message']);
$this->setEmptyMessage('battle-end');
$this->setResponse(true, 'end');
return;
--省略
/**
* 追加効果の処理
*
* @param Pokemon:object $atk
* @param Pokemon:object $def
* @param Move:object $move
* @return array
*/
private function effectMove($atk, $def, $move)
{
$effects = $move->effects($atk, $def);
// メッセージが取得できたらセット
if(isset($effects['message']) && isset($effects['sa'])){
// 状態異常有り
$effect_id = issueMsgId();
$sa = new $effects['sa'];
setMessage($effects['message'], $effect_id);
setResponse([
'param' => json_encode([
'name' => $sa->getName(),
'color' => $sa->getColor()
]),
'action' => 'sa',
'target' => $def->getPosition()
], $effect_id);
}elseif(isset($effects['message'])){
// メッセージのみ返却
setMessage($effects['message']);
}
// バトル終了
if(isset($effects['end'])){
setEmptyMessage('battle-end');
setResponse(true, 'end');
// バトル終了判定
return $effects;
}
}
effects後の記述量が多くなったため、effectMoveメソッド内にまとめました。
まず、effectMoveのメソッドにeffectsを呼び出すために必要な値を引数で渡し、effectsメソッドを呼び出します。配列または全くの空値が返ってくるため、issetを使ってsaとmessageの両方が返ってくれば、メッセージIDを生成してレスポンスと合わせて返却します。今回は新しくsaというactionを指定し、対象ポケモンをtargetにセット、状態異常の名称(name)と色(color)をjson形式でparamにセットしました。
ふきとばし等の技ではバトル終了処理が挟まれるため、effectMove後に再度配列をチェックし、endキーに値が存在していればバトル終了処理をして処理を終了させています。
状態異常のセット
それでは、演出をするフロント側(JavaScript)の処理を見ていきましょう。
バトル用メッセージJS(/Public/Assets/js/Battle/message.js)
/*----------------------------------------------------------
// 処理内で呼び出す関数
----------------------------------------------------------*/
/**
* メッセージアクション
* @param now element
* @return Promise
**/
var actionMsgBox = function(now){
return new Promise( async (resolve, reject) => {
// 最終メッセージかどうか確認
if((now.length === 0) || now.hasClass('last-message')){
await doLastMsg();
}else{
// メッセージにアクションがセットされていれば実行
switch (now.data('action')){
// ==============================================
// HPバーの処理 =================================
//
case 'hpbar':
await doAnimateHpBar(
now.data('target'),
now.data('param')
);
break;
// ==============================================
// 経験値バーの処理 =============================
//
case 'expbar':
await doAnimateExpBar(
now.data('param')
);
break;
// ==============================================
// レベルアップ処理 =============================
//
case 'levelup':
await doAnimateLevelUp(
now.data('param')
);
break;
// ==============================================
// 状態異常処理 =================================
//
case 'sa':
await doAnimateSa(
now.data('target'),
now.data('param')
);
break;
// ==============================================
}
// 次のメッセージへ
await nextMsg(now);
}
resolve();
});
}
// ==============================================
// 状態異常処理 =================================
//
/**
* 状態異常をセット
* @param json
* @return Promise
**/
var doAnimateSa = function (target, param){
return new Promise ((resolve, reject) => {
var badge = $('#sa-' + target);
badge.removeClass("badge-");
badge.addClass("badge-" + param.color);
badge.text(param.name);
resolve();
});
}
分岐に状態異常を追加して、必要箇所にクラスとネームをセットする単純な処理です。状態異常エリアを判別するために、IDを割り振りました。
それでは、実際の動きを見てみましょう。
これで状態異常の演出処理は完了です。
まとめ
いかがだったでしょうか。
今回のPHPポケモンでは「状態異常演出」の方法をご紹介しました。
演出自体は些細なものですが、これを実現するために全体の構成を大きく変更しました。システム開発でも、たまにこういったことが起こり得ます。ですが、そうならないためにも事前に要件定義をしっかり立てて、設計していくことが作業負担の軽減に繋がります。
システムエンジニアを目指している方や、WEBプログラミングに興味がある方は、ぜひ参考にしてみてくださいね。