プログラミング

戦闘不能による交代編 PHPポケモン84

PHP PHPポケモン ポケモン
戦闘不能による交代編 PHPポケモン84

戦闘不能による交代

ポケモンが戦闘不能になった際、もし手持ちに戦える状態のポケモンが残っていれば「交代」か「逃げる」の2択になります。今までは手持ちポケモンが1匹のみで判定を行っていたので、今回は交代の選択肢も含めて勝負の判定の見直しをしていきます。

 

パーティーを含めた勝負判定

味方または相手のポケモンがひんし状態になると、コントローラーのjudgmentメソッドで勝ち負けの分岐を行っています。ここに、パーティーを含めた判定処理を加え、もしまだ戦える状態であれば選択肢が出るように新しい分岐を追加します。

 

バトルコントローラー用トレイト(/App/Traits/Controller/BattleControllerTrait.php
/**
* バトル結果判定
* @return void
*/
private function judgment(): void
{
    // 味方がひんし状態になった
    if(battle_state()->isFainting('friend')){
        // 戦闘可能なパーティーを確認
        if(player()->isFightParty()){
            // パーティーが残っている
            if(battle_state()->isFainting('enemy')){
                // 相手が瀕死状態 → バトル終了
                $this->judgmentWin();
            }else{
                // 相手が瀕死状態ではない → ポケモン交代の確認
                $msg_id = issueMsgId();
                setMessage('次のポケモンを使いますか?', $msg_id);
                // レスポンスデータをセット
                setResponse([
                    'toggle' => 'modal',
                    'target' => '#'.$msg_id.'-modal'
                ], $msg_id);
                // モーダル用のレスポンスをセット
                setModal([
                    'id' => $msg_id,
                    'modal' => 'change-or-run'
                ]);
                waitForceModal($msg_id);
            }
        }else{
            // 全滅(負け)
            $this->judgmentLose();
        }
    }else if(battle_state()->isFainting('enemy')){
        // 相手がひんし状態になった(味方はひんし状態ではない)
        // 勝ち
        $this->judgmentWin();
    }
}
 
/**
* バトル結果(負け)
* @return void
*/
private function judgmentLose()
{
    // 全滅
    setMessage(player()->getName().'は、目の前が真っ暗になった');
    // バトル終了判定用メッセージの格納
    setEmptyMessage('battle-end');
}
 
/**
* バトル結果(勝ち)
* @return void
*/
private function judgmentWin()
{
    // 経験値の計算
    $party = player()->getParty();
    $order = battle_state()->getOrder();
    // パーティー取得
    $exp = $this->calExp(friend(), enemy());
    // 経験値をポケモンにセット
    $party[$order]->setExp($exp);
    // 努力値を獲得
    $party[$order]->setEv(enemy()->getRewardEv());
    // もしポケモンが「へんしん状態」であれば変更後の状態を引き継ぎ
    if(friend()->checkSc('ScTransform')){
        friend()->judgmentTransform($party[$order]);
    }
    // 散らばったお金の取得
    $money = battle_state()->getMoney();
    if($money){
        setMessage(player()->getName().'は、'.$money.'円拾った');
        player()->addMoney($money);
    }
    // バトル終了判定用メッセージの格納
    setEmptyMessage('battle-end');
}

 

もし味方ポケモンが瀕死状態になり、パーティーに戦える状態のポケモンが残っていれば、「逃げる」または「次のポケモンを選ぶ」の選択肢を表示したモーダルを起動させています。

 

モーダルは以下の通りです。

 

交代または逃げるの選択モーダル(/Resources/Partials/Battle/Modals/change-or-run.php
<!-- Modal -->
<div class="modal fade" id="<?=$modal['id']?>-modal" tabindex="-1" role="dialog" aria-labelledby="<?=$modal['id']?>-modal-title" aria-hidden="true" data-keyboard="false" data-backdrop="static">
    <div class="modal-dialog modal-dialog-centered modal-sm" role="document">
        <div class="modal-content">
            <div class="modal-body">
                <p class="mb-0">次のポケモンを選びますか?</p>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-sm btn-success" data-toggle="modal" data-target="#party-modal">ポケモンを選ぶ</button>
                <button type="button" class="btn btn-sm btn-danger" data-submit_remote="run">逃げる</button>
            </div>
        </div>
    </div>
</div>

 

強制表示モーダル

選択しなければモーダルは原則閉じれないようにしていますが、もし更新等をされた場合は再度判定処理が行われてしまいます。これでは、画面の更新を行えば逃げられない相手であっても回数を重ねることで逃げられるようになり、ゲーム性が失われてしまいます

これを防ぐためにも、強制的に選択を問うモーダルは「強制表示モーダル」として登録、更新後はモーダルを強制起動させる必要があります。

そのために、モーダルセット後に以下のメソッドを呼び出しています。

waitForceModal(識別ID);

 

強制表示させるとしても、その場で強制状態にすれば更新などイレギュラーな読み込み以外でもメッセージを無視して表示されてしまいます。それを防ぐためにも、通常セット後には強制表示を待機状態として用意、画面の読み込みが全て終わったあとに待機状態から強制表示へと切り替えます。

 

レスポンスクラス(/Classes/Response.php
/**
* 強制表示モーダルの初期化
* @return void
*/
public function initForceModal(): void
{
    unset($_SESSION['__data']['force_modal']);
}
 
/**
* 強制表示モーダルのセット
* @param id:string
* @return boolean
*/
public function setForceModal($id): bool
{
    // 強制表示させるモーダルを取得
    $key = array_search($id, array_column($this->modals, 'id'));
    // 見つかればセッションへ格納
    if($key !== false){
        $_SESSION['__data']['force_modal'] = $this->modals[$key];
        // ID重複回避のためモーダル内から取り除く
        unset($this->modals[$key]);
        return true;
    }
    return false;
}
 
/**
* 強制表示モーダルを待機状態にする(更新等された際に強制表示)
* @param id:string
* @return void
*/
public function waitForceModal($id): void
{
    $this->wait_force_modal = $id;
}
 
/**
* 強制表示モーダルを待機状態にする(更新等された際に強制表示)
* @param id:string
* @return boolean
*/
public function setWaitForceModal(): bool
{
    // 待機中の強制表示モーダルがあれば、セッションへ格納
    if($this->wait_force_modal){
        $this->setForceModal($this->wait_force_modal);
        $this->wait_force_modal = '';
        return true;
    }
    // 待機中なし
    return false;
}
 
/**
* 強制表示モーダルの存在確認
* @return boolean
*/
public function isForceModal(): bool
{
    if(isset($_SESSION['__data']['force_modal'])){
        return true;
    }
    return false;
}
 
/**
* 強制表示モーダルの取得
* @return array
*/
public function getForceModal(): array
{
    return $_SESSION['__data']['force_modal'] ?? [];
}
 
/**
* 強制表示モーダルの確認
* @return boolean
*/
public function isForceModalTarget($target): bool
{
    if(
        isset($_SESSION['__data']['force_modal']['existing_modal']) &&
        $_SESSION['__data']['force_modal']['existing_modal'] === $target
    ){
        return true;
    }
    return false;
}

 

クラス内保管では再読み込み時にデータが失われてしまうため、セッションを活用しています。待機状態で登録したモーダルは、画面最終でセッションへ移動させる必要があるので、コアファイルの最終部分で置き換え用のメソッド(setWaitForceModal)を起動しています。

これで、もし再読み込みをされても強制モーダルを起動することで選択肢を問うことができます。

 

強制モーダルはフッターで存在チェックをしてから読み込み、存在する場合はjsで強制起動させましょう。

 

フッター(/Resources/Partials/Layouts/Foot/footer.php
# 強制モーダルの読み込み
if(isForceModal()){
    $modal = getForceModal();
    // 既存モーダルを使用しない場合は読み込み
    if(isset($modal['modal'])){
        include($root_path.'/Resources/Partials/'.getPageName(true).'/Modals/'.$modal['modal'].'.php');
    }
    echo '<input type="hidden" id="force-modal" value="'.($modal['existing_modal'] ?? '#'.$modal['id'].'-modal').'">';
}

 

共通JS/Public/Assets/common.js
/**
 * 強制モーダルの起動
 * @function modal
 */
var showForceModalInit = function(){
    $(document).ready(function() {
        var force_modal = $('#force-modal');
        if(force_modal.length){
            $(force_modal.val()).modal('show');
        }
    });
}

 

戦闘からの離脱

選択肢の1つである「逃げる」は、戦えるポケモンを選ばずにバトルを終了させることができます。ただし、通常時の逃げると同様で逃走判定が行われ、失敗すれば次のポケモンを選出しなければなりません。

このときの逃げる判定は、ひんし状態になったポケモンのステータスを参考に算出するため、RunServiceを少しカスタマイズすることで実装します。

 

逃げるサービス(/App/Services/Battle/RunService.php
/**
* @return void
*/
public function execute()
{
    // にげるのカウントを進める
    battle_state()->run();
    if($this->checkRun()){
        // 逃走成功
        setMessage('上手く逃げ切れた');
        // バトル終了判定用メッセージの格納
        setEmptyMessage('battle-end');
    }else{
        // 逃走失敗
        $msg_id = issueMsgId();
        setMessage('逃げられない!', $msg_id);
        if(friend()->isFight()){
            // 相手のターン処理
            $this->enemyTurn();
        }else{
            // ひんし状態での逃走失敗
            setResponse([
                'toggle' => 'modal',
                'target' => '#party-modal'
            ], $msg_id);
            setModal([
                'id' => $msg_id,
                'existing_modal' => '#party-modal' # 既存モーダルの使用
            ]);
            // 強制表示モーダルを待機状態にする
            waitForceModal($msg_id);
            // 判定不要処理
            battle_state()->judgeFalse();
        }
    }
    // バトルポケモンが瀕死状態なら、強制モーダルを初期化
    if(!friend()->isFight()){
        initForceModal();
    }
}

 

もし味方が瀕死状態でこのサービスが呼び出された際は、ひんし状態での2択による処理ということが判別できます。その際は逃走失敗後に相手の行動を行わず、ポケモン選択のモーダルを強制表示待機状態でセットして返却しています。

 

サービス終了後、コントローラーでは瀕死状態をチェックして判定処理を行っています。このまま返却すれば再度判定処理が実施されてしまうので、回避用にバトル状態クラスへ判定不要フラグを追加、状態を確認してjudgementを制御しましょう。

 

バトル状態クラス(/Classes/BattleState.php
/**==================================================================
* 判定確認用フラグ
==================================================================**/
 
/**
* 判定不要にする処理
* @return void
*/
public function judgeFalse(): void
{
    $this->judgement = false;
}
 
/**
* 要判定にする処理
* @return void
*/
public function judgeTrue(): void
{
    $this->judgement = true;
}
 
/**
* 判定有無の確認
* @return boolean
*/
public function isJudge(): bool
{
    return $this->judgement;
}

 

次のポケモンを選ぶ

最後に今回の本題となるポケモンの選出についてです。ポケモンを選ぶためのモーダルは、パーティーモーダルをそのまま使用しています。

交代処理は通常時と同じくChangeServiceを活用できるように、こちらも味方が瀕死状態かどうかを確認することで、相手の行動が行われないようにします。

 

ポケモン交代サービス(/App/Services/Battle/ChangeService.php
/**
* @return void
*/
public function execute()
{
    // バリデーション
    if(!$this->validation()){
        return;
    }
    // 瀕死チェック後に交代処理を行う(friendのポケモンが入れ替わるため)
    if(!friend()->isFight()){
        // 瀕死状態からの交代
        $this->change();
        // モーダル初期化
        initForceModal();
    }else{
        // 通常の交代処理
        $this->change();
        // 相手のターン処理
        $this->enemyTurn();
    }
}

  

それでは、ひんし状態から交代の流れを確認してみましょう。

 

ひんし後の判定から交代まで正常に機能していますね。これでポケモン交代の一連の流れが完成です。

 

まとめ

いかがだったでしょうか。

今回のPHPポケモンでは、「戦闘不能による交代」の実装方法をご紹介しました。

WEBプログラミングでフォームを活用する際には、画面移管による初期状態の生成が厄介なポイントです。これを解決するためには、全体の構成に気をつけることの他に、JSを主軸としたSPA(シングルページアプリケーション)による構築が候補となります。

現在プログラミング学習に取り組んでいる方は、ぜひ参考にしてみてくださいね。

 

注目の記事

フレンドリィショップ編 開店準備 PHPポケモン 75
プログラミング
PHP,PHPポケモン,ポケモン
フレンドリィショップ編 開店準備 PHPポケモン 75

アイテム(どうぐ) PHPポケモンもバトル機能が一通り揃ってきたので、新機能として「アイテム」の実装に取り掛かります。 アイテムにも色々ありますが、技やポケモンのクラス同様に、初代で登場したアイテムから順番に取り揃えていきましょう。   キズぐすりの実装 ポケモンのどうぐ、一番手は「キズぐすり」...

フィールド効果技編(しろいきり) PHPポケモン 50
プログラミング
PHP,PHPポケモン,ポケモン
フィールド効果技編(しろいきり) PHPポケモン 50

フィールド効果技とは ポケモンの技の中には、ポケモンに対して状態変化や異常を与えるもの以外に、フィールド自体に効果を持たせるものがいくつかあります。PHPポケモンでは未実装ですが、そういったフィールド効果技はポケモンを交代したとしても場に効果が残り続けます。  場の状態(ポケモンwiki) https:/...

フリーランスの最大の敵は休日!?正しい休息の取り方教えます
フリーランス
フリーランス,独立
フリーランスの最大の敵は休日!?正しい休息の取り方教えます

  フリーランスになりたての人は、仕事のペースがわからなかったり、無理に自分へ追い込みをかけて頑張ろうとしてしまうことがあります。 毎日を仕事でいることが、フリーランスにとっての心がけや意識のあり方としては大切ですが、それをそのままの意味で実行してしまうと明らかなオーバーペースになるのは事...

ピカチュウから学ぶオブジェクト指向 〜レベルシステム導入編〜 3
プログラミング
PHP,PHPポケモン,オブジェクト指向,ポケモン
ピカチュウから学ぶオブジェクト指向 〜レベルシステム導入編〜 3

  大人気?シリーズ「ピカチュウから学ぶオブジェクト指向」、今回はレベルシステムの導入編です。   第1回(基礎編)、第2回(クラス継承編)で作成したPokemonとPikachuのクラスを使用するので、最初から学習したい人はぜひご参考ください。      レベルシステムの導入   ポケモンのゲ...

PHPポケモン「コントローラー編」〜POSTとSESSIONの活用〜 10
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「コントローラー編」〜POSTとSESSIONの活用〜 10

  今回のPHPポケモンでは、今まで作った機能用のコントローラーになるインターフェースを作成します。ポケモンやメソッドを選択できるようにして、よりゲーム性の高いアプリケーションを実装しましょう。   第1回から学習したい方はコチラ     コントローラーの実装   それでは実装したアクション...

ノーコード開発で将来プログラミングは不要?我々は何を学ぶべきなのか
プログラミング
amazon,AWS,Honeycode,NoCode,プログラミング学習
ノーコード開発で将来プログラミングは不要?我々は何を学ぶべきなのか

  近年、プログラミングの需要は増え勢いを増していますが、それ以上にノーコードというソースコードを打たなくでもアプリ開発ができるというソフトウェアやプラットフォームが普及してきました。 これにより一部の期待感とは別に、プログラマーという職業は今後不要になるのではないかと危機感を抱く人が出て...

状態異常演出編 PHPポケモン 62
プログラミング
PHP,PHPポケモン,ポケモン
状態異常演出編 PHPポケモン 62

状態異常の演出 今回は「状態異常」にかかった際の動的な変更、演出を実装していきます。 どく状態になれば、メッセージに合わせて「どく」を表記、まひ状態になれば、メッセージに合わせて「まひ」をセットするという単純なものです。   返り値の変更 それではまず、状態異常をセットしてメッセージを生成して...

SEが心がけるべき3つの習慣
プログラミング
Automator,JavaScript,エンジニア,システムエンジニア,プログラマー,プログラミング
SEが心がけるべき3つの習慣

  ネット社会、在宅ワークが主流になってきた今、SEという仕事に憧れを頂いている人は多くなりました。 単価の良さも、魅力の一つです。そして、技術が普及してきたことにあわせて、便利なソフトやアプリが簡単に手に入るようになり、一昔前と比べると技術の習得も容易になりました。   しかし、多くの人が...

カテゴリ

SEO対策 イベント デザイン ネットワーク ビジネスモデル フリーランス プログラミング マーケティング ライティング 動画編集 雑記

タグ

5G Adobe AfterEffects AI ajax amazon Animate api artisan atom Automator AWS Bluetooth CSS CVR description EC-CUBE4 ECショップ ESLint Facebook feedly foreach function Google Google AdSense Honeycode htaccess HTML IEEE 802.11ax Illustrator Instagram IoT JavaScript jQuery jQuery UI keyword LAN Laravel Linux MacBook MAMP meta MLM MySQL NoCode note OS OSI参照モデル Paypal Photoshop PHP phpMyAdmin PHPポケモン PremierePro rss SEO SEO対策 Sequel Pro Skype SNS SSH Symfony TCP/IP title Toastr Trait Twig Twitter UCC V系 WAN WebSub Wi-Fi wiki Windows WordPress XAMPP xml Xserver YouTube YouTuber Zoom アーティスト アウトプット アクセス層 アニメーション アフィリエイト イーブイ インターネット インプット エンジニア オブジェクト指向 お金配り クリック単価 クリック数 コミュニケーション能力 コロナ コンサルティング サムネイル システムエンジニア スタートアップ スタイルシート スパム データベース ディープフェイク デザイナー デザイン テレワーク ナンパ ニュース ネットワークモデル ノマドワーク バナー ピカチュウ ビジネス フィード フリーランス ブロガー ブログ プログラマー プログラミング プログラミング学習 プログラミング教育 プロトコル ホームページ制作 ポケモン マークアップ マーケティング メール リモートワーク レンダリング 三井住友 三宮 仕事依頼 児童デイ 児童デイサービス 児童発達支援 公開鍵 初心者 助成金 勉強法 営業 広告 広告収入 必勝マニュアル 放課後等デイサービス 朝活 楽天 深層学習 無線LAN 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力