プログラミング

戦闘不能による交代編 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(シングルページアプリケーション)による構築が候補となります。

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

 

注目の記事

プログラミングとは?現役システムエンジニアが教える裏事情
プログラミング
システムエンジニア,プログラマー
プログラミングとは?現役システムエンジニアが教える裏事情

  プログラミングってよくわからない? 実際に何をやっているの?   最近注目されているSE(システムエンジニア)やPG(プログラマー)という職業ですが、「そもそもプログラミングとは?」といった疑問を抱えている方も多いですね。 今回は、そういった方へ向けて「プログラミングの基礎知識と裏事情」...

PHPポケモン「UI(Bootstrap4の導入)編」コード配布・デモ有り 13
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「UI(Bootstrap4の導入)編」コード配布・デモ有り 13

  第13回のPHPポケモンは「UI編」ということで、CSSの大人気フレームワークBootstrapさんにお手伝いいただきます。 また、前回実装したレスポンス機能により進化のアクションに一部不具合が出ていたので、このあたりも合わせて修正をしながら進めていきましょう。   Bootstrapを導入するにあたり、今までin...

PHPポケモン「状態異常編〜まひ〜」23
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「状態異常編〜まひ〜」23

  今回のPHPポケモンでは「状態異常」を導入します。バトルシステムにも関係してくる部分ですが、それ以外にも影響を与える部分が多く、且つ非常に判定がややこしく、作り込む必要があったため1つずつ片付けていきます。   状態異常の実装  ポケモンの除隊異常に該当するものは以下の7通りです。 ...

千利休から学ぶビジネスモデルの作り方3ステップ!守破離とは
ビジネスモデル
千利休から学ぶビジネスモデルの作り方3ステップ!守破離とは

  千利休の利休道歌に以下のような記述があります。 規矩作法 守り尽くして破るとも離るるとても本を忘るな    これは武道や芸道など学びの基礎として考えられ、創造過程のベースとして用いられてきました。これはビジネスモデルを作り上げるという観点から見ても非常に重要かつ、失敗する多くの人が疎...

ピカチュウから学ぶオブジェクト指向 〜入門編〜 1
プログラミング
PHP,PHPポケモン,オブジェクト指向,ポケモン
ピカチュウから学ぶオブジェクト指向 〜入門編〜 1

オブジェクト指向とは  オブジェクト指向プログラミング https://ja.wikipedia.org/wiki/オブジェクト指向プログラミング オブジェクト指向プログラミングとは、互いに密接な関連性を持つデータとメソッドをひとつにまとめてオブジェクトとし、それぞれ異なる性質と役割を持たせたオブジェクトの様々な定...

初心者必見!仕事がデキる人のIllustrator活用術3選
デザイン
Adobe,Illustrator,サムネイル
初心者必見!仕事がデキる人のIllustrator活用術3選

  仕事の速い人の大半は、「効率の良い方法」や「便利な使い方」を知っていて使いこなしています。これは、デザインの現場でも同じです。 今回はその中でもIllustratorで知っておくと便利な機能を3つご紹介します。この3つを押さえておくだけで、作業効率は格段にアップするので、これからソフトの使い方を覚...

レビューがアフィになる!?SNS式ECサイトとは【ビジネス企画書】
ビジネスモデル
ECショップ,SNS
レビューがアフィになる!?SNS式ECサイトとは【ビジネス企画書】

  多くの人が利用しているSNS 副業やフリーランスに人気なアフィリエイト   それぞれの良い点を上手く利用すれば、完成するビジネスはないか?と考えて思い浮かんだ企画です。 今回は「レビューがアフィになる!?SNS式ECサイトとは」について、新時代のショッピングモール式ネットショップの企画をご紹...

PHPポケモン「レベルアップ進化編」9
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「レベルアップ進化編」9

  PHPポケモン(旧:ピカチュウから学ぶオブジェクト指向)も第9回目となりました。前回GitHubよりコードを配布したので、これから学習しようと考えている人は、ぜひ参考にしてください。   最初からコードの内容について学びたい人は、ぜひ記念すべき第1回から順を追って取り組んでみてください。   ...

カテゴリ

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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力