プログラミング

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
「諦めが上手い人」ほど成功する!正しい目標の立て方とは

  「諦めたらそこで試合終了ですよ」   漫画の中でも有名なセリフですが、これからあなたは何を読み取りますか? 何か目標を達成するために努力が必要とされますが、その方法がわからずに試行錯誤したり、そもそも挑戦すらできずに終えてしまう人は多いのです。 努力をした人は、ほとんどがそれは結果的...

PHPポケモン「わざ編〜わるあがき〜」35
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「わざ編〜わるあがき〜」35

わるあがき そろそろ技のPPを実装段階にきたので、その前に「わるあがき」という技を作成しましょう。「わるあがきって何?」という人のために、どういった技なのか簡単に説明します。 全ポケモン使用可能。ただし、レベルアップなどで普通のわざとして覚えることはできず、自分の技がすべて選択不能になった場合...

動画にカラオケテロップを入れる編集方法【AfterEffectsで色変わりの文字】
動画編集
Adobe,AfterEffects
動画にカラオケテロップを入れる編集方法【AfterEffectsで色変わりの文字】

  動画に声と同じタイミングでテロップを入れたい カラオケのような文字はどうやっていれればいいの?   一見簡単に見えるものも、いざ導入しようとすればどうやればいいかわからない、そんなこと多いのではないでしょうか? 今回はAdobe AfterEffectsを使った方法をご紹介します。些細な編集が動画のク...

教師が勝ち組!?出会い&学習の超正統派マッチングサービスとは【ビジネス企画書】
ビジネスモデル
マーケティング
教師が勝ち組!?出会い&学習の超正統派マッチングサービスとは【ビジネス企画書】

  「出会いがない」   社会人になると多くの人が抱く悩みの1つです。職場の男女比率や年齢層が理由の人もいれば、同じ職場での出会いは求めていない人もいるでしょう。 今回はそんな「出会い」を解決するための企画「出会い&学習の超正統派マッチングサービス」について、企画案と考察をまとめました。   ...

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

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

コンテンツ配信業でバズるために大切な3つの法則〜『1ヶ月でチャンネル登録者数1000人』は参考にするな
マーケティング
YouTube,YouTuber,ブログ
コンテンツ配信業でバズるために大切な3つの法則〜『1ヶ月でチャンネル登録者数1000人』は参考にするな

  YouTubeやブログを始めたけど思ったように伸びない・・・   こういった人は、チャンネル登録者数を伸ばす方法などの動画を見ても参考にならなく、結果に繋がらないという場合がほとんどです。 その理由は、その人自身に問題があるわけではなく、動画の前提条件がそもそも違っているからです。   今回は「...

引き継ぎ考慮のメッセージID重複回避編 PHPポケモン 58
プログラミング
PHP,PHPポケモン,ポケモン
引き継ぎ考慮のメッセージID重複回避編 PHPポケモン 58

今回のPHPポケモンでは内部の作り込みをしていきます。見た目への反映は無いので、プレイを楽しみにしている人や、ポケモンが好きで毎日チェックしてくれているような人は、ブラウザをバックしてもらって問題ありません。   それでは、前々回辺りから保留にしていた「メッセージIDに重複回避対策」についてです。 &...

そらをとぶ&あなをほる編 PHPポケモン46
プログラミング
PHP,PHPポケモン,ポケモン
そらをとぶ&あなをほる編 PHPポケモン46

チャージ中の回避技 以前は「ロケットずつき」や「ソーラービーム」をサンプルとしてチャージ技を実装しましたが、今回は少し特別な効果をもったチャージ技を実装します。それが「そらをとぶ」と「あなをほる」です。これらは初代ポケモンでも重宝される技であり、チャージ中に相手からの攻撃を回避することができま...

カテゴリ

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