プログラミング

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

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

 

注目の記事

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

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

【Adobe Animate CC】モーショントゥイーンを使ったアニメーション作成
動画編集
Adobe,Animate,Illustrator,Photoshop,アニメーション
【Adobe Animate CC】モーショントゥイーンを使ったアニメーション作成

    今回はキャラクターがうちわを扇いでいるアニメーションのAdobe Animateを使った作成方法をご紹介します。 完成イメージは以下の通りです。   Photoshopなどを使ってもgifアニメーションの作成はできますが、Adobe Animateのモーショントゥイーンを使えば、変化するポイントだけを設定す...

忘れさせる技選択 前編(覚えるのを諦める) PHPポケモン 55
プログラミング
PHP,PHPポケモン,ポケモン
忘れさせる技選択 前編(覚えるのを諦める) PHPポケモン 55

忘れさせる技の選択 PHPポケモンでは技習得時に忘れさせる技の選択が出来ず、古いものから順番に消えていっていました。ですが、これでは主力技として使っているものが、覚えたくもない技に消されてしまうということが起こってしまいます。 実際のゲームでも、技を覚えようとした際に既に最大数の4枠が埋まっていれ...

迷惑メールはなぜ届く?amazonや楽天を騙る悪質メールへの対処法とは
ネットワーク
amazon,スパム,メール,楽天
迷惑メールはなぜ届く?amazonや楽天を騙る悪質メールへの対処法とは

「いきなり迷惑メールが届くようになった」 「Amazonや楽天を装ったメールはどうやって見分ければいいの?」   知らない人からいきなり連絡が届いたり、登録もしていないようなサービスからメールが届けば、それは詐欺メールかも知れません。 スマホやパソコンが一般的に普及して、ネットでの買い物やサービスを利用...

ポケモン預かりシステム編 システムの実装 PHPポケモン 87
プログラミング
PHP,PHPポケモン,ポケモン
ポケモン預かりシステム編 システムの実装 PHPポケモン 87

ポケモン預かりシステムの実装 システムの仕様とクラスも整ってきたので、いざ実装をしていきましょう。 前回までに作成した項目で、いくつか変更になったものがあるので、まずはじめに挙げておきます。   シャットダウン機能 ボックスの選択を解除するというものでしたが、こちらを不採用にしました。ボックスは...

パーティー実装編 戦闘に参加するポケモン PHPポケモン64
プログラミング
PHP,PHPポケモン,ポケモン
パーティー実装編 戦闘に参加するポケモン PHPポケモン64

先頭のポケモンを選出 前回パーティーのプロパティを準備して、複数(6匹)のポケモンを持ち歩けるようにすることを想定しました。 今回は、そこからバトル画面への連動をさせる部分までを作り込んでいきましょう。   複数のポケモンを所有している場合、戦闘が始まって繰り出されるのは「ひんし状態を除く一番上...

レポート(試験)編 PHPポケモン 94
プログラミング
PHP,PHPポケモン,ポケモン
レポート(試験)編 PHPポケモン 94

今回の内容は、あくまで試験的なものとなります。実際にそのままの仕組みで導入するかは未定です。 ※セーブ機能の実装自体は予定しております   また、今回はセーブするための仕組みの部分にのみにフォーカスを当てています。非公開ディレクトリやパーミッション等による最低限の対応は施していますが、試験的にア...

デザインとブランディングが生み出す本当の価値とは
デザイン
UCC
デザインとブランディングが生み出す本当の価値とは

  商品やHPなど様々なところで価値を提供している「デザイン」ですが、それがもつ本当の意味や価値というものは意外と知られていません。 一般的にはイメージを作る・伝えるということで要求されるものですが、突き詰めた先には人間の深層心理に働きかけるブランディングという要素が潜んでいるのです。   今...

カテゴリ

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