プログラミング

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

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

 

注目の記事

CSSとの意外な関係「よくわかるSEO対策」スタイルシート編
SEO対策
CSS,スタイルシート,レンダリング
CSSとの意外な関係「よくわかるSEO対策」スタイルシート編

   今回の「よくわかるSEO対策」はスタイルシート(CSS)編です。   多くの人が 「SEO対策なのに、CSSの説明をするの?」 と思うかも知れませんが、これには意外な関係性があったのです。   現在CSSを学んでいる人、そしてCSSの書き方ならマスターしているといった人でも、SEOのことまでを考慮した記述ができて...

EC-CUBE4内にWordPressを設置(共存)する方法
SEO対策,プログラミング
EC-CUBE4,PHP,Symfony,Twig,WordPress
EC-CUBE4内にWordPressを設置(共存)する方法

今回使用したバージョン EC-CUBE4.0.5 WordPress5.6 ※EC-CUBE4、WordPressのカスタマイズは自己責任でお願いします。また、現在稼働中のサイトで試す際には、必ずバックアップを取ってから行なうようにしてください。   EC-CUBE4とは ネットショップを作るとなれば、様々なサービスが出回っ...

甘い誘惑に気をつけよう「わからないことへの対処法」
雑記
甘い誘惑に気をつけよう「わからないことへの対処法」

  最近は開発記事が多めだったので、今回は気分転換も込めてみんな大好きコラムのコーナーです。開発疲れという理由ももちろんありますが、久々に考えを書き綴りたくなったというのが本音です。   今回のテーマは「甘い誘惑に気をつけよう」です。高校生ぐらいまではあまり縁がなかったことでも、大学生・社会...

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

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

フリーランスが見積書を作るときに押さえておきたい3つのポイント+α
フリーランス
フリーランス,仕事依頼,独立,見積書
フリーランスが見積書を作るときに押さえておきたい3つのポイント+α

  仕事の依頼がきたけど、どれぐらいの金額を提示すればいいかわからない   駆け出しのフリーランスや、これから独り立ちしようとしている人に多い悩みです。 今回はそういった方のために「フリーランスが見積書を作るときに押さえておきたい3つのポイント+α」についてご紹介します。     時給...

ポケモン入れ替え編 PHPポケモン 83
プログラミング
PHP,PHPポケモン,ポケモン
ポケモン入れ替え編 PHPポケモン 83

ポケモンの入れ替え 複数ポケモンの所有、そして並び替えの機能が整ったので、いよいよバトルでのポケモン交代機能を実装します。ポケモンがバトル中に交代する方法は大きく分けて以下の4つです。 プレイヤー操作による交代 ひんしによる交代 相手ポケモンの技による交代 味方ポケモンの技による交代 ...

ピカチュウから学ぶオブジェクト指向 〜ステータス導入編〜 6
プログラミング
PHP,PHPポケモン,オブジェクト指向,ポケモン
ピカチュウから学ぶオブジェクト指向 〜ステータス導入編〜 6

  PHPをピカチュウ(ポケモン)から学ぶ大人気コーナー、第6回目は「ステータス機能の導入編」です。   前回(第5回)で終了段階でのサンプルコードを公開しているので、もし本記事から始める人はぜひそちらを参考にしてください。    ※お詫び   調べたところによると、ポケモンの経験...

今からできる!ブログのアクセスを爆UPさせる3大SNS活用法
マーケティング
Facebook,Instagram,Twitter,ブロガー,ブログ
今からできる!ブログのアクセスを爆UPさせる3大SNS活用法

  ブログを収益化させたいけど、なかなかアクセス数が増えない 記事の質は高いのに、その良さをどうやって伝えれば良いかわからない   SEO対策をする上でも、収益化するためにも記事のクオリティは重要です。 しかし、せっかく良い記事を書いていても、そのブログや記事の存在を伝えることができなけれ...

カテゴリ

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