プログラミング

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構造などが変更になればそれだけ修正しなければならない箇所が多いということがわかりますね。それだけ開発では設計が重要なのです。

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

 

注目の記事

進化アニメーション 後編 PHPポケモン 60
プログラミング
PHP,PHPポケモン,ポケモン
進化アニメーション 後編 PHPポケモン 60

ポケモンの進化演出 前回に続いて、ポケモンの進化演出を実装していきます。バックエンドの処理はざっと説明をしたので、今回はフロントエンド(JavaScript)側の処理を作成していきましょう。   進化画面は新しく設けたので、こちらにもバトル画面で使っているメッセージ用JSを作成していきます。処理自体はほとん...

SEO対策で役立つ!ライティングスキルを向上させる3ステップ
ライティング
SEO,ブログ
SEO対策で役立つ!ライティングスキルを向上させる3ステップ

  ブログやメール、SNSなどライティングスキルが問われる場面が多く、それは質に直結しています。各プラットフォームによって特徴はありますが、基礎的な文章力自体がついていれば多様な場面で役立つことは間違いありません。 文章の質が高くなれば、ブログであればSEOに強い価値のあるサイトになりますし、SNS...

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

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

英語できたらブログで稼げる 【ネオコピペ】
ライティング
ブログ,翻訳,英語
英語できたらブログで稼げる 【ネオコピペ】

  2010年に楽天が社内公用語の英語化を宣言したのは、多くの人が耳にしたことがあるでしょう。 私からすると、「英語ができることは強み」だという考えから、「これからは英語ができないと行きていけないのでは?」と考えを変えさせられるような、そんな出来事でした。   多言語できるデメリットを見つけるのは難...

HPバーアニメーション 後編 フロント側の対応 PHPポケモン 44
プログラミング
PHP,PHPポケモン,ポケモン
HPバーアニメーション 後編 フロント側の対応 PHPポケモン 44

HPバーアニメーション それでは前回に続き、HPバーのアニメーションづくりをしていきましょう。前回、メッセージに合わせてレスポンスを返却するというサーバー側の仕組みを作成しました。なので、今回はそれをフロント側で受け取り、タイミングよくアニメーションで再現します。   フロント側(js)の処理 前回...

【税金は貰うもの】知って得する!お金を稼ぐための実践的な3要素
マーケティング
【税金は貰うもの】知って得する!お金を稼ぐための実践的な3要素

  「お金を稼ぐための基本的な3要素」に続く、「実践的な3要素」です。 前回は、単価、頻度、客数の関係を理解すれば、お金を稼ぐ仕組みがどのように成立しているのか、そしてどういったアプローチをすればお金を稼げるのかがわかりました。   今回は、直接お金に関係する実践的な3要素です。どう...

PHPポケモン「オートロード編(修正版)」17 おまけ:日本語化
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「オートロード編(修正版)」17 おまけ:日本語化

  前回実装したオートローダーの使い方が盛大に間違っていたので、今回その間違いの説明をしながら、正しい実装方法をご紹介します。 申し訳ありません。(誠意)    オートロードについて(再)  必要なタイミングで必要なファイルをrequireまたはincludeするあれです。   前回spl_autoload_reg...

いかり編 PHPポケモン 42
プログラミング
PHP,PHPポケモン,ポケモン
いかり編 PHPポケモン 42

いかり(技)とは 2020年10月段階での最新シリーズである「ソード・シールド」では、今まであった技が使用不可能になっているものが数多くあります。その1つが「いかり」という技です。 いかり(ポケモンwiki) https://wiki.ポケモン.com/wiki/いかり   使えなくなっている技の中には、世代を経...

カテゴリ

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