プログラミング

PHPポケモン「技ポイント(PP)編」36

PHP PHPポケモン ポケモン
PHPポケモン「技ポイント(PP)編」36

技ポイント(PP)とは

ポケモンではそれそれの技に使用回数が定められています。それが技ポイント(PP)と呼ばれているものです。

PP(ポケモンwiki

 

技のクラスを実装した際に、それぞれにppというプロパティをもたせて回数をセットしています。これが、対象の技を使える基本最大回数です。もしすべての技の使用回数がなくなってしまうと、技を使うことができなくなるため前回実装した「わるあがき」が発動します。

 

PPを管理するためにも、現在ポケモンに対して格納している技(move)のプロパティの格納形式を、以下のような多次元連想配列に変更します。

 

ポケモンクラスの技プロパティ
$move = [
    0 => [
        'class' => 技クラス名(string),
        'remaining' => 残り回数(integer),
        'correction' => 補正値(integer),
    ],
];

 

classキーの値には、今まで値として格納していた技クラス名が入ります。では追加された残りの2つを見ていきましょう。

 

残り回数

remainingキーに割り当てられている値は、技の残り回数です。「でんきショック」であれば、基本最大使用回数が30回なので、全回復状態で1度技を使えば、残りは29回となります。この数を格納して置かなければ、あと何回使用できるかがチェックできませんよね。

技を習得した時点では、残り回数はその技の最大数が格納されます。でんきショックであれば、覚えた段階の残り回数は30回となります。

 

補正値

correctionキーに割り当てられている値は、技の最大回数に対する補正値です。ポイントアップなどのアイテムを使うと、技の上限回数を増やすことができます。

最大PPの増え方には3段階あり、1段階ごとに元のPP1/5増え、最大まで上げれば元のPP8/5(=1.6)となる

 

補正値の初期値は0です。現段階では補正値を増やす手段はありませんが、こちらも今後実装するものと考え用意しました。残り回数の算出も、補正値の概念が存在するものとして作成していきます。

 

 

それでは、ポケモンの技プロパティが変更したことによって修正しなければならない箇所を1つずつ対応していきましょう。まずは技クラスからです。

 

技クラス(/Classes/Move.php
/**
* 使用回数の取得
*
* @param integer $correction 補正値
* @return integer
*/
public function getPp(int $correction=0)
{
    return $this->pp + (int)(floor($this->pp / 5) * $correction);
}

 

使用回数の取得メソッド(getPp)に補正値の計算を追加しました。引数に補正値をセットすると、最大回数に補正値x20%数を加算して返却しています。ポケモンの技回数は5区切りのため、小数点以下の数値が出ることはありませんが、念の為切り捨て処理を行なっています。

 

次に技の習得処理を修正します。

 

Set格納トレイト(/Traits/Pokemon/SetTrait.php
/**
* 初期技をセットする
* @return void
*/
protected function setDefaultMove()
{
    foreach($this->level_move as list($level, $move)){
        if($level <= $this->level){
            // 現在レベル以下の技であれば習得
            $this->setMove(new $move);
        }else{
            // 現在レベルを超えていれば処理終了
            break;
        }
    }
}
 
/**
* 技を覚える
* @return object Move
*/
protected function setMove($move)
{
    $this->move[] = [
        'class' => get_class($move),
        'remaining' => $move->getPp(),
        'correction' => 0,
    ];
    if(count($this->move) > 4){
        // 技が4つを超過していれば、一番上を忘れさせる
        unset($this->move[0]);
        // 技の添字を採番する
        $this->move = array_values($this->move);
    }
}

 

ポケモンが持つmoveプロパティの構造が変更になったので、それに合わせた形式でセットするようにsetMoveメソッドを変更しました。引数は今までクラス名(string)で受け取っていましたが、オブジェクトで受け取る仕様に変更しました。remainingには先程作成したgetPpを引数無しで格納し、補正値であるcorrectionには0をセットしています。

 

setMovedefaultMoveメソッド内で呼び出しているので、引数にオブジェクトを渡せるように、newをつけておきましょう。

 

次に覚えている技を取得するメソッド(getMove)を修正します。

 

Get格納トレイト(/Traits/Pokemon/GetTrait.php
/**
* 覚えている技の一覧を取得する
* @param integer $num
* @param string
* @return array
*/
public function getMove($num=null, $param='')
{
    if(is_null($num)){
        // 全返却
        if($param === 'array'){
            // 配列(加工不要)で返却
            return $this->move;
        }else{
            // array_mapで配列内の技クラスをオブジェクト化して返却
            return array_map(function($move){
                // 無名関数
                return [
                    'class' => new $move['class'],
                    'remaining' => $move['remaining'],
                    'correction' => $move['correction'],
                ];
            }, $this->move);
        }
    }else{
        // 番号指定で返却
        $move = $this->move[$num] ?? $this->move[0];
        if($param === 'array'){
            // 配列(加工不要)で返却
            return $move;
        }else{
            // オブジェクトにして返却
            return new $move['class'];
        }
    }
 
}

 

最後に技の一覧出力方法を修正して、残りPPが確認できるようにしておきましょう。

 

ホーム画面詳細モーダル(Resources/Partials/Home/Modals/details.php
<div class="tab-pane fade show" id="move" role="tabpanel" aria-labelledby="move-tab">
    <?php # 覚えている技 ?>
    <table class="table table-bordered table-sm table-hover">
        <thead class="thead-light">
            <tr>
                <th scope="col">覚えている技</th>
                <th scope="col">タイプ</th>
                <th scope="col">PP</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach($pokemon->getMove() as $move): ?>
                <tr class="move-detail-link" data-target="#move_<?=get_class($move['class'])?>-content">
                    <th scope="row" class="w-50"><?=$move['class']->getName()?></th>
                    <td><?=$move['class']->getType()->getName()?></td>
                    <td><?=$move['remaining']?>/<?=$move['class']->getPp($move['correction'])?></td>
                </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
    <?php # 技説明 ?>
    <div class="overflow-auto p-3 border" style="height:160px;">
        <?php foreach($pokemon->getMove() as $key => $move): ?>
            <div class="move-detail-content <?php if(array_key_first($pokemon->getMove()) == $key) echo 'active'; ?>" id="move_<?=get_class($move['class'])?>-content">
                <h6><?=$move['class']->getName()?></h6>
                <hr>
                <p><?=$move['class']->getDescription()?></p>
            </div>
        <?php endforeach; ?>
    </div>
</div>

 

 

初期状態では技ポイントが減っていないので、数値から判断することは出来ませんが、エラーが出ていないことが確認できればOKです。

詳細と同じように、バトル画面でのPP表示も残数が出力されるよう変更しておきましょう。

 

バトルシステムへの導入

それでは、バトルシステムにPPを導入していきます。通常、すべての技PPが0回であれば技選択ができず、「たたかう」を選んだ時点でわるあがきが発動しますが、まずは技PPが減る処理と、使用時に技ポイントが残っているかどうかを確認して、なければ「わるあがき」が発動するという処理を実装しましょう。

  

使用可不可の判定

 まずは技の使用可不可の判定です。こちらを行動チェックの直後に追加しましょう。

 

攻撃用トレイト(/Traits/Battle/AttackTrait.php
/**
* 攻撃
* (攻撃→ダメージ計算→ひんし判定)
*
* @param object $atk_pokemon
* @param object $def_pokemon
* @param object $move
* @return void
*/
protected function attack($atk_pokemon, $def_pokemon, $move)
{
    // 行動チェック(状態異常・状態変化)
    if(!$this->checkBeforeSa($atk_pokemon) || !$this->checkBeforeSc($atk_pokemon)){
        // 行動失敗
        return;
    }
    // わざの使用可不可判定
    if(!$this->checkEnabledMove($move, $atk_pokemon)){
        $this->setMessage($atk_pokemon->getPrefixName().'は出すことのできる技がない');
        // わるあがきをセット
        $move = new Struggle;
    }
    // チャージチェック
    if($move->charge($atk_pokemon)){
        // チャージターンならメッセージを格納して行動終了
        $this->setMessage($atk_pokemon->getMessages());
        $atk_pokemon->resetMessage();
        return;
    }

 

checkEnabledMoveというメソッドを使い、使える技かどうかを確認しています。ここで使えない技だと判定された場合は、わるあがきをセットして以降の処理を進めていきます。

 

では、新しく作成したcheckEnabledMoveメソッドの処理を見てみましょう。

 

チェック用トレイト(/Traits/Battle/CheckTrait.php
/**
* 技の使用可不可判定
*
* @param object $move Move
* @param object $pokemon Pokemon
* @return boolean (true: 使用可, false:使用不可(わるあがき))
*/
protected function checkEnabledMove(object $move, object $pokemon)
{
    $move_class = get_class($move);
    if($move_class === 'Struggle'){
        // わるあがき
        return false;
    }
    // ポケモンの技一覧
    $move_list = $pokemon->getMove(null, 'array');
    // 選択された技の添番を取得
    $num = array_search(
        $move_class,
        array_column($move_list, 'class'),
    );
    // PP残数の確認
    if($move_list[$num]['remaining'] > 0){
        // 使用可能
        // チャージターンは残PPそのまま
        if(!$this->checkChargeTurn($pokemon, $move)){
            // 残PPをマイナス1
            $pokemon->calRemainingPp('sub', 1, $num);
        }
        return true;
    }else{
        // 使用不可
        return false;
    }
}
 
/**
* チャージターンかどうかの確認
*
* @param object $pokemon
* @param object $move
* @return boolean
*/
protected function checkChargeTurn($pokemon, $move)
{
    // チャージ技ではない
    if(!$move->getChargeFlg()){
        return false;
    }
    // 状態変化を取得
    $sc = $pokemon->getSc();
    // 現在未チャージ状態
    if(!isset($sc['ScCharge'])){
        // チャージターン
        return true;
    }
    // 残チャージターン数が1超過
    if($sc['ScCharge']['turn'] > 1){
        // チャージターン
        return true;
    }
    // チャージターンではない
    return false;
}

 

最初に技が「わるあがき」かどうかをチェックしています。これは技選択がされなかった場合にわるあがきが選択された状態で処理に入るため、最初にチェックをして該当すればfalseを返却し、そのままわるあがきを実行してもらいます。

 

その後、技ポイントのチェックをして使用回数が残っていれば、残りPPをマイナス1して使用可(true)、もし残数が残っていなければ使用不可(false)を返却しています。ただし、チャージ技の場合、チャージターンに技ポイントが引かれてしまうと1回の使用でPPが2減少してしまうため、checkChargeTurnというメソッドを使ってこのターンがチャージターンかどうかを確認しています。

 

※多次元配列のキーを使った検索方法(array_searchとarray_columnの組み合わせ)は以下の記事にまとめているので参考にしてください

【PHP】可変長引数とは「点(ドット)3つ」 多次元連想配列の検索 【PHP】可変長引数とは「点(ドット)3つ」 多次元連想配列の検索

可変長引数とは  引数の数が決まっていない、状況に応じて複数の引数を指定したいときに、関数の引数で指定する点(ドット)3つのことです。PHP5.6以降で使用することができます。  PHPマニュアル 可変長引数リスト https://www.php.net/manual/ja/functions.arguments.php#functions.variable-arg-list ...

  

残りポイントの計算

次に、残りPPを変更するために使っているcalRemainingPpメソッドの処理を見ていきましょう。こちらは残りHPを取得する処理と同じように、引数を指定することで加算とリセットができるようにしています。

 

計算用トレイト(/Traits/Pokemon/CalculationTrait.php
/**
* 残りPPの計算
*
* @param string $param
* @param integer $val (default:0)
* @param integer $num (default:null)
* @return integer
*/
public function calRemainingPp(string $param, int $val=0, $num=null)
{
    switch ($param) {
        // リセット処理
        case 'reset':
        if(is_null($num)){
            // すべてのPPを全回復
            foreach($this->getMove() as $key => $move){
                $this->move[$key]['remaining'] = $move['class']->getPp($move['correction']);
            }
        }else{
            // 指定された技PPを全回復
            $this->move[$num]['remaining'] = $this->move[$num]
            ->getPp($this->move[$num]['correction']);
        }
        break;
        // 減算処理
        case 'sub':
        if(is_null($num)){
            // すべてのPPに減算処理
            foreach($this->move as $key => $move){
                $this->move[$key]['remaining'] -= $val;
                if($this->move[$key]['remaining'] < 0){
                    // 最小値の処理
                    $this->move[$key]['remaining'] = 0;
                }
            }
        }else{
            // 指定された技PPに減算処理
            $this->move[$num]['remaining'] -= $val;
            if($this->move[$num]['remaining'] < 0){
                // 最小値の処理
                $this->move[$num]['remaining'] = 0;
            }
        }
        break;
        // 加算処理
        case 'add':
        if(is_null($num)){
            // すべてのPPに加算処理
            foreach($this->getMove() as $key => $move){
                $this->move[$key]['remaining'] += $val;
                if($this->move[$key]['remaining'] > $move['class']->getPp($move['correction'])){
                    // 最大値の処理
                    $this->move[$key]['remaining'] = $move['class']->getPp($move['correction']);
                }
            }
        }else{
            // 技をインスタンス化
            $move = new $this->move[$num];
            $this->move[$num]['remaining'] += $val;
            if($this->move[$num]['remaining'] > $move->getPp($this->move[$num]['correction'])){
                // 最大値の処理
                $this->move[$num]['remaining'] = $move->getPp($this->move[$num]['correction']);
            }
        }
        break;
    }
}

 

リセットが選択された場合はすべての技PPを全回復(補正値を含めた最大PPをセット)、加算と減算では指定された値の計算結果をそれぞれセットしています。残りHPの計算処理とは異なり、どの技のPPを変更するかを指定できなければならないため、第3引数では技番号(添え番)を受け取っています。

分岐の関係上、記述量が多くなっていますが、処理自体は加算減算後に上限下限を確認しているという至って簡単な処理となっています。

 

それでは、実際に技を使って確認してみましょう。

 

 

 

 

 

 

 

 

戦闘終了後、使った技のPPが使用回数分減っていることが確認できました。これでPPシステムの実装は完了です。

 

まとめ

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

今回のPHPポケモンでは「技ポイント(PP)システムの導入方法」をご紹介しました。

PHPポケモンではDBを使用しないため、クラスのプロパティを活用していますが、DB構造などが変更になればそれだけ修正しなければならない箇所が多いということがわかりますね。それだけ開発では設計が重要なのです。

現在プログラミングを学習中の方は、ぜひ参考にしてみてくださいね。

 

注目の記事

ポケモンプロパティ編(全国図鑑No・捕捉率・重さ) PHPポケモン 77
プログラミング
PHP,PHPポケモン,ポケモン
ポケモンプロパティ編(全国図鑑No・捕捉率・重さ) PHPポケモン 77

PHPポケモン記事も記念すべき第77回を迎えることができ、これもひとえに皆様のお力があってのことです。いろんな方のご協力もあり(ドット絵とかドット絵とかドット絵とか)見た目はかなりゲームらしくなってきました。 しかし、肝心のゲーム要素が本家と比べればまだまだ機能も少なく未実装の項目も多いので、これ...

PHPポケモン「技ポイント(PP)編」36
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「技ポイント(PP)編」36

技ポイント(PP)とは ポケモンではそれそれの技に使用回数が定められています。それが技ポイント(PP)と呼ばれているものです。 PP(ポケモンwiki) https://wiki.ポケモン.com/wiki/PP   技のクラスを実装した際に、それぞれにppというプロパティをもたせて回数をセットしています。これが、対象の技...

PHPポケモン「状態異常+逃走編〜ねむり・こおり・やけど・どく〜」24
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「状態異常+逃走編〜ねむり・こおり・やけど・どく〜」24

状態異常の実装  今回は、前回作成した「まひ」を参考に、「ひんし」を除いた残りの状態異常も実装していきます。    クラスの作成  まずはそれぞれのクラスを作成します。前回解除時のメッセージを設定出来ていなかったので、まひと合わせて実装していきましょう。   状態異常:やけど(...

フリーランスの仕事の取り方教えます!この3つを押さえておけばOKです【企業も応用可】
フリーランス
フリーランス,独立,起業
フリーランスの仕事の取り方教えます!この3つを押さえておけばOKです【企業も応用可】

  仕事ってどうやってとればいいの?   独立したい、起業したいと考えている人の多くが、仕事はどうやってとればいいのかと悩んで足踏みしています。 実は、基本的な3つのポイントさえ知っていれば、継続して仕事を受注することは簡単です。 今回は自分が実際にやっていることを例に「フリーランスなら...

PHPポケモン「バトルシステム編〜経験値の獲得〜」29
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「バトルシステム編〜経験値の獲得〜」29

経験値の獲得 今まではポケモンに直接経験値を与えるというチートびっくりの仕様でしたが、バトルシステムも終盤に差し掛かってきたので「倒したポケモンから経験値を取得する」というごく当たりまえの仕様を導入していきます。   基礎経験値の設定 では、経験値の計算式に入る前に、必要なパラメーターを1つ用...

捕獲処理実装編 PHPポケモン 80
プログラミング
PHP,PHPポケモン,ポケモン
捕獲処理実装編 PHPポケモン 80

捕獲処理の作成 前回モンスターボールのクラスを作成したので、今回は捕獲判定までの一連の処理を仕上げていきます。サービス自体は他のアイテムと一緒にするためItemServiceを呼び出し、その中で使用されたアイテムを判断して分岐を作ります。   バトル中のアイテムサービス(/App/Services/Battle/ItemService.ph...

オウムがえし編 PHPポケモン 68
プログラミング
PHP,PHPポケモン,ポケモン
オウムがえし編 PHPポケモン 68

オウムがえしとは 今回は久々に新しい技を実装します。それが「オウムがえし」です。 オウムがえし(ポケモンwiki) https://wiki.ポケモン.com/wiki/オウムがえし   初代で登場した技であり、序盤に登場するポッポやオニスズメがレベルアップで覚える技の1つです。最新世代ではオウムがえしという技は実...

連続の技習得編 オブジェクトをセッションへ格納 PHPポケモン57
プログラミング
PHP,PHPポケモン,ポケモン
連続の技習得編 オブジェクトをセッションへ格納 PHPポケモン57

セッション経由でのオブジェクト引き継ぎ 技習得の処理が整ってきたので、ここで連続技習得・連続レベルアップ時にも問題なく動作するように作り込んでいきます。ですが、現状のモーダルをレスポンスやメッセージと同様に、そのまま引き継いだとしてもエラーが発生します。 その原因がセッション経由でのオブジェク...

カテゴリ

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

タグ

5G Adobe AfterEffects AI ajax amazon Animate api artisan atom Automator AWS Bluetooth CSS CVR description EC-CUBE4 ECショップ ESLint Facebook feedly foreach fortify function Google Google AdSense Honeycode htaccess HTML IEEE 802.11ax Illustrator Instagram IoT JavaScript jetstream jQuery jQuery UI keyword LAN Laravel Linux MacBook MAMP meta MLM MySQL NoCode note OS OSI参照モデル Paypal Photoshop PHP phpMyAdmin PHPポケモン PremierePro rss 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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 認証 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力