プログラミング

ポケモン入れ替え編 PHPポケモン 83

PHP PHPポケモン ポケモン
ポケモン入れ替え編 PHPポケモン 83

ポケモンの入れ替え

複数ポケモンの所有、そして並び替えの機能が整ったので、いよいよバトルでのポケモン交代機能を実装します。ポケモンがバトル中に交代する方法は大きく分けて以下の4つです。

  1. プレイヤー操作による交代
  2. ひんしによる交代
  3. 相手ポケモンの技による交代
  4. 味方ポケモンの技による交代

 

プレイヤー操作による交代

バトル操作画面で、パーティーからポケモンを選ぶことで交代が可能です。これが最も標準的な交代方法であり、今回のメイン実装部分となります。

 

ひんしによる交代

味方のポケモンが瀕死状態になった際に、次のポケモンを使うかどうかを問われます。このとき、味方が全滅していなければ選択肢は「にげる」か「交代」のどちらかになります。逃げるが失敗した際には、強制的に交代ポケモンを選ばせる必要があります。

 

相手ポケモンの技による交代

「ふきとばし」「ほえる」などの技による強制交代です。現在PHPポケモンでは野生ポケモンとのバトル機能しか実装されていないため、一旦この技による入れ替え機能は保留とします。

 

味方ポケモンの技による交代

「とんぼがえり」などの技を使用すると、相手にダメージを与え且つポケモンを交代することができます。ただし、初代の技で同様の効果をもつ技は存在していないため、こちらも一旦保留とします。

 

戦闘ポケモンの交代処理

まずはプレイヤー操作による「戦闘ポケモンの交代」について見ていきましょう。

パーティー一覧では、現在ポケモンをクリックすると詳細が表示されます。しかし、これを選択により「入れ替え」か「詳細(様子をみる)」のどちらかを選べるようにする必要があります。 なので、バトル画のパーティー画面にのみ表示されるボタンをフッター部分に追加します。

<?php # フッター(バトル画面) ?>
<?php if(getPageName() === 'battle'): ?>
    <div class="modal-footer">
        <?php foreach(player()->getParty() as $order => $party): ?>
            <button class="btn btn-sm btn-success"
            data-action="details"
            data-toggle="modal"
            data-dubble_modal="true"
            data-target="#pokemon<?=$order?>-details-modal"
            data-order="<?=$order?>"
            style="display:none;">
            様子を見る</button>
        <?php endforeach; ?>
        <button class="btn btn-sm btn-secondary" data-btn="default" data-action="details" disabled>様子を見る</button>
        <form id="partner-change-form" method="post">
            <?php input_token(); ?>
            <input type="hidden" name="action" value="change">
            <input type="hidden" name="order">
            <button type="submit" class="btn btn-sm btn-secondary" data-selected="<?=battle_state()->getOrder()?>" disabled>入れ替える</button>
        </form>
    </div>
<?php endif; ?>

 

ポケモンの行選択に合わせて、該当するボタンを表示させていきます。「様子を見る」ではモーダルを起動させる必要があるため、dataプロパティが設定されています。こちらは定数のため、パーティー数ボタンを用意して表示非表示の判定で切り替えています。

※documentからの指定をすれば変数のように扱うことも可能です

 

交代ボタンについては、現在選出されているポケモンや、瀕死状態のポケモンには交代できないようにdisabledの判定を加えていきます。以下JavaScriptの処理です。

 

バトル画面用パーティーJS/Public/Assets/js/Battle/party.js
/*----------------------------------------------------------
// 初期化する関数
----------------------------------------------------------*/
/**
* ポケモンの選択
* @function on.click
* @return void
**/
var selectPartnerInit = function(){
    $('[data-list="party"] > .table-selected-row').on('click', function(){
        var order = $(this).data('order');
        var fight = $(this).data('fight');
        // 「入れ替える」の判定
        var change_btn = $('#partner-change-form button[type="submit"]');
        // 現在バトル中のポケモン番号異なり、戦闘可能
        if(
            order !== change_btn.data('selected') &&
            fight
        ){
            // 入れ替えボタンを有効化してinputに番号をセット
            change_btn.prop('disabled', false)
            .removeClass('btn-secondary')
            .addClass('btn-primary');
            $('#partner-change-form [name="order"]').val(order);
        }else{
            // 入れ替えボタンを無効化して番号をリセット
            change_btn.prop('disabled', true)
            .removeClass('btn-primary')
            .addClass('btn-secondary');
            $('#partner-change-form [name="order"]').val('');
        }
        // 「様子を見る」の判定
        $('button[data-action="details"]').hide();
        $('button[data-action="details"][data-target="#pokemon' + order + '-details-modal"]').show();
    });
}
 
/**
* モーダル起動時の初期化
* @function change
* @return void
**/
var showPartyModalInit = function(){
    $('#party-modal').on('show.bs.modal', function(){
        // 選択中のポケモンを初期化
        $(this).find('[data-list="party"] > .table-selected-row')
        .removeClass('active');
        // 「様子を見る」を初期化
        $(this).find('button[data-action="details"]')
        .hide();
        $(this).find('[data-btn="default"][data-action="details"]')
        .show();
        // 「入れ替える」を初期化
        $('#partner-change-form button[type="submit"]').prop('disabled', true)
        .removeClass('btn-primary')
        .addClass('btn-secondary');
    });
}
 
/*----------------------------------------------------------
// 初期化
----------------------------------------------------------*/
jQuery(function($){
    selectPartnerInit();
    showPartyModalInit();
});

 

ポケモンが選択されれば、それに合わせてボタンの判定を行っています。入れ替えボタンはformに埋め込んだsubmitになっているため、選択されたポケモンが戦闘可能であれば番号をinputにセットしています。

 

それでは、ポケモン交代用に新しくサービスを作成しましょう。

 

ポケモンの入れ替えサービス(/App/Services/Battle/ChangeService.php
<?php
$root_path = __DIR__.'/../../..';
// 親クラス
require_once($root_path.'/App/Services/Service.php');
// トレイト
require_once($root_path.'/App/Traits/Service/Battle/ServiceBattleAttackTrait.php');
require_once($root_path.'/App/Traits/Service/Battle/ServiceBattleEnemyTurnTrait.php');
require_once($root_path.'/App/Traits/Service/Battle/ServiceBattleAttackAfterTrait.php');
require_once($root_path.'/App/Traits/Service/Battle/ServiceBattleCheckTrait.php');
require_once($root_path.'/App/Traits/Service/Battle/ServiceBattleEnemyAiTrait.php');
require_once($root_path.'/App/Traits/Service/Battle/ServiceBattleOrderGenelatorTrait.php');
require_once($root_path.'/App/Traits/Service/Battle/ServiceBattleExTrait.php');
require_once($root_path.'/App/Traits/Service/Battle/ServiceBattleCalTrait.php');
 
/**
 * 交代
 */
class ChangeService extends Service
{
 
    use ServiceBattleAttackTrait;
    use ServiceBattleEnemyTurnTrait;
    use ServiceBattleAttackAfterTrait;
    use ServiceBattleCheckTrait;
    use ServiceBattleEnemyAiTrait;
    use ServiceBattleOrderGenelatorTrait;
    use ServiceBattleExTrait;
    use ServiceBattleCalTrait;
 
    /**
    * @return void
    */
    public function __construct()
    {
        //
    }
 
    /**
    * @return void
    */
    public function execute()
    {
        // バリデーション
        if(!$this->validation()){
            return;
        }
        // 交代処理
        $this->change()
        // 相手のターン処理
        $this->enemyTurn();
        }
    }
 
    /**
    * 検証
    * @return bool
    */
    private function validation(): bool
    {
        /**
        * 現在と同じ → false
        * 存在しない → false
        * ひんし → false
        */
        $partner = player()->getPartner(request('order'));
        if(
            request('order') === battle_state()->getOrder() ||
            empty($partner) ||
            !$partner->isFight()
        ){
            return false;
        }
        return true;
    }
 
    /**
    * 交代処理
    * @return void
    */
    private function change(): void
    {
        $partner = player()->getPartner(request('order'));
        // 現在のバトルポケモンのバトルステータス関係を初期化
        friend()->releaseBattleStatsAll();
        battle_state()->changeInit('friend');
        // ポケモンを戻す演出処理
        $msg_id1 = issueMsgId();
        setMessage(friend()->getNickname().'、戻れ!', $msg_id1);
        setResponse([
            'action' => 'change-in',
            'target' => 'friend'
        ], $msg_id1);
        // バトル中のポケモンを交代してポケモン番号を変更
        battle_state()->setFriend($partner, true);
        // 交代後のポケモンを繰り出す演出処理
        $msg_id2 = issueMsgId();
        setMessage('ゆけっ!'.friend()->getNickname().'!', $msg_id2);
        setResponse([
            'action' => 'change-out',
            'target' => 'friend',
            'param' => json_encode([
                'class' => get_class($partner),
                'name' => $partner->getNickname(),
                'level' => $partner->getLevel(),
                'hp_max' => $partner->getStats('HP'),
                'hp_now' => $partner->getRemainingHp(),
                'hp_per' => $partner->getRemainingHp('per'),
                'hp_color' => $partner->getRemainingHp('color'),
                'sa' => $partner->getSaName(),
                'sa_color' => $partner->getSaColor(),
                'exp' => $partner->getPerCompNexExp(),
            ])
        ], $msg_id2);
    }
 
}

 

受け取ったポケモン番号が、交代可能なものかをチェックして交代処理を行っています。判定はフロント側と同様で、現在と異なっているか、ひんし状態ではないかです。直接操作で「存在しない番号」が飛んでくる可能性も考慮して、バックエンドでは追加で存在確認を最初に行っています。

 

もしこの3つをクリアすれば、現在のポケモンのバトルステータスを全て解除、へんしんやターンダメージ等も含め全てリセットを行い、格納されているバトルポケモンを交代しています。

演出用のレスポンスですが、ポケモンを戻す際のものと、ポケモンを登場させる際に必要になるパラメーターをメッセージに合わせて返却しています。新しいポケモンのものに書き換えるためには必要な値が多いため、json形式で返却しています。

  

入れ替えの演出

それでは、サービス側でされた値を使って、表示ポケモンの書き換え処理を行いましょう。ポケモン入れ替えでは「戻す」と「登場」の2つの演出が必要になるので、それぞれ別の関数で作成していきましょう。

 

関数のグローバル化

演出の関数が多くなってきたため、このタイミングでJavaScriptの関数をグローバル化させてファイル分けしても呼び出せるようにしていきます。今回は「window」にオブジェクトを追加する方法を採用しました。

 

アクション関数のまとめJS/Public/Assets/js/Battle/library-action.js
// グローバル関数をオブジェクト化
window.actionLib = {};
 
/**
* 交代処理(戻す)
* @param json
* @return Promise
*/
window.actionLib.doAnimateChangeIn = function (target){
    return new Promise ((resolve, reject) => {
        // 対象のポケモン画像とパラメーターを非表示
        $('#' + target + '-pokemon-image').hide();
        $('#' + target + '-pokemon-parameter').css('opacity', 0);
        resolve();
    });
}
 
/**
* 交代処理(登場)
* @param json
* @return Promise
*/
window.actionLib.doAnimateChangeOut = function (target, param){
    return new Promise ( async (resolve, reject) => {
        // 交代後のポケモンの画像を生成
        var img = $('#' + target + '-pokemon-image');
        img.attr('src', '/Assets/img/pokemon/dots/back/' + param.class + '.gif')
        // HPの生成
        var hpbar = $('#hpbar-' + target);
        hpbar.css('width', param.hp_per + '%');
        hpbar.attr('aria-valuenow', param.hp_now);
        hpbar.attr('aria-valuemax', param.hp_max);
        hpbar.removeClass(function(index, className) {
            // 背景色クラスを全リセット
            return (className.match(/\bbg-\S+/g) || []).join(' ');
        });
        hpbar.addClass('bg-' + param.hp_color);
        $('#remaining-hp-count-' + target).text(param.hp_now);
        $('#max-hp-count-' + target).text(param.hp_max);
        // 状態異常の生成
        var sa = $('#sa-' + target);
        sa.text('');
        if(param.sa){
            sa.text(param.sa)
            .removeClass(function(index, className) {
                // バッジ色クラスを全リセット
                return (className.match(/\bbadge-\S+/g) || []).join(' ');
            })
            .addClass('badge-' + param.sa_color);
        }
        // レベル・名前
        $('#level-friend').text(param.level);
        $('#name-friend').text(param.name);
        // 経験値
        var expbar = $('#expbar-friend');
        expbar.css('width', param.exp + '%');
        expbar.attr('aria-valuenow', param.exp);
        // ボールが開くエフェクト
        $('#battle-field').append(
            $($('#template-effect-ball-open').html())
            .addClass('friend')
        );
        await timer(500);
        // ボールエフェクトを非表示
        $('img.capture-ball-open').hide();
        // 画像とパラメーターを表示
        img.show();
        $('#' + target + '-pokemon-parameter').css('opacity', 100);
        await timer(1000);
        resolve();
    });
}

 

windowのオブジェクトにactionLibのキーを追加し、その中に空オブジェクトを格納してから関数をセットしています。これで、別ファイルでもwindowオブジェクトを参照することで関数を自由に呼び出すことができます。

※本格的なJSを使ったアプリケーションを検討している方には、クラス管理やフレームワークでの開発をオススメします

 

処理自体の記述量は多いですが、内容は至って単純です。

ポケモンを戻す際には、対象のポケモンとHPバーなどを含めたブロックを非表示にしています。両方をhidedisplay:none)にしてしまうと、高さが変動することでガタつきが出てしまうので、高さがあるHPバーのブロックは不透明度を0にすることで擬似的に非表示状態としています。

※min-heightを使ってcssでの処理でもOKです

 

ポケモンの登場演出は、非表示にした各要素に対してPHPから受け取ったパラメーターを順に嫉妬していきます。HPバーや状態異常のカラーについては、一旦removeClassで全て取り除いてから、再度受け取ったカラー値をセットしています。

演出の時間を調整するため、await timer(ミリ秒)を使って調整しています。

/**
* タイマー
* @param time:integer
* @return Promise
*/
var timer = function(time){
    return new Promise( async (resolve, reject) => {
        setTimeout(() => { resolve(); }, time);
    });
}

 

使用するエリアがasync関数になっていれば、setTimeoutで囲わず同期的な処理を記述することができるので、今回のような演出処理を作る際には便利です。

 

それでは、ポケモンの入れ替え演出について見てみましょう。

 

交代後に相手ポケモンの行動が問題なく行われ、入れ替え自体も問題なく終えることができました。

これで単純なバトル中のポケモン交代処理は完成です。

  

まとめ

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

今回のPHPポケモンでは「ポケモンの交代処理」の実装方法についてご紹介しました。

バトル中のポケモンをクラスによる管理に替えたことで、全体的な処理自体がスムーズになりました。

プログラミング学習中の方や、ゲームづくりに興味がある人は、是非参考にしてみてくださいね。

 

注目の記事

プログラミングでフリーランスを目指す人にPHP学習をオススメする3つの理由
プログラミング
Laravel,PHP,SEO,WordPress
プログラミングでフリーランスを目指す人にPHP学習をオススメする3つの理由

  「フリーランスになるためにプログラミングを身に着けたい」 「セカンドキャリアで技術を習得したい」 「副業でパソコン1台で稼げるものに挑戦したい」   終身雇用が危ぶまれている現在、スキルを身に着けて転職やフリーランスとして活躍したいと考える人が増え、プログラミングの需要は年々高まってきて...

LANとWANについて【第2回 ド素人のためのネットワーク講座】
ネットワーク
IoT,LAN,WAN,Wi-Fi
LANとWANについて【第2回 ド素人のためのネットワーク講座】

  YQUALがお送りする、ド素人のためのネットワーク講座。 栄えある第2回は「LANとWANについて」です。   フロントエンジニアや現在プログラミングを学習中の方を中心に、ネットワークについての基礎的理解を深めていくための内容になっています。 ざっくりとした説明で物足りない、または細かく見ていった...

なぜ、お金を配るの?悪質メール・SNSを利用した詐欺的手法への対処法とは
ネットワーク
amazon,SNS,Twitter,お金配り,楽天,迷惑メール
なぜ、お金を配るの?悪質メール・SNSを利用した詐欺的手法への対処法とは

定期的に書きたくなるコラムのコーナー! 今回は、迷惑メールやSNSのDMを活用した悪質な勧誘、巷で流行っているお金配りを隠れ蓑のした巧妙な詐欺的手法などをいくつかご紹介、その対策・リクス回避の方法をまとめました。   まず結論からお伝えすると 「怪しいと思うなら手を出すな」 です。その詳細を知りたい...

PHPポケモン「野生ポケモン遭遇編」18
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「野生ポケモン遭遇編」18

  PHPポケモンが第18回にしていよいよバトルの第一歩、野生ポケモンとの遭遇編に突入です。 新しいコントローラーの作成と、バトル画面の作成、そしてポケモンデータの受け渡しなどを中心にご紹介します。   バトル画面の実装  ポケモンのゲームでも、野生ポケモンが現れるとバトル画面へ移管し...

ゆびをふる編 PHPポケモン 69
プログラミング
PHP,PHPポケモン,ポケモン
ゆびをふる編 PHPポケモン 69

ゆびをふるとは 今回PHPポケモンで実装する技は「ゆびをふる」です。  ゆびをふる(ポケモンwiki) https://wiki.ポケモン.com/wiki/ゆびをふる   「ゆびをふる大会」というゆびをふるのみを使った大会なども開催されているということもあり、ポケモンの技の中でも初代から長く愛されてきた1つです。で...

本は読まなくていいの!?物事の本質を理解する
雑記
読書
本は読まなくていいの!?物事の本質を理解する

  成功したけりゃ、1日1冊本を読め   社会人になると、本を読めと言われることは多いのではないでしょうか。 特にアクティブな活動をしていると、また独立や起業などを夢見ている人は、そういった言葉を聞くことは多いはずです。   しかし一方で、「本は読まなくても良い」という成功者たちもいます。 ...

ダメージ固定技編(ちきゅうなげ・カウンター) PHPポケモン 41
プログラミング
PHP,PHPポケモン,ポケモン
ダメージ固定技編(ちきゅうなげ・カウンター) PHPポケモン 41

ダメージ固定技とは PHPポケモンでも作成したダメージ計算機能ですが、ポケモンの技の中にはそれを必要としない技がいくつかあります。それが「固定ダメージ技」です。 ポケモンwiki(ダメージ固定技) https://wiki.ポケモン.com/wiki/ダメージ固定技 ステータスに依存せず、わざ自体にダメージ量が決...

バトルステータス可視化編 PHPポケモン 70
プログラミング
PHP,PHPポケモン,ポケモン
バトルステータス可視化編 PHPポケモン 70

バトルステータスの可視化 現在のポケモンでは、バトルステータスの現状を可視化できるようになっており、どれぐらいのランク補正がかかっているか、フィールドがどういう状態になっているかがわかるようになっています。 初代、第2世代等では確認できなかった内容ではありますが、システムとしては便利な要素でも...

カテゴリ

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