プログラミング

PHPポケモン「バトルシステム編〜HP計算〜」26

PHP PHPポケモン ポケモン
PHPポケモン「バトルシステム編〜HP計算〜」26

HP計算

これまでに実装したダメージ計算ですが、計算はできていてもお互いに相手ポケモンのHPを削ることはできませんでした。なので、今回は実際のバトルのように、HPに対してダメージを与えるという仕組みを作成していきます。

 

残りHP

ここで必要になるのが「残りHP」という概念です。今までステータス上のHPは存在していましたが、現在どれぐらい残りがあるのかまでは用意していませんでした。なので、これをポケモンに対して持たせ、且つ状態異常などとともにステータスの引き継ぎ対象としましょう。

  

プロパティの設定

 まずは残りHPを格納するためのプロパティをポケモンクラスに用意します。

 

ポケモンクラス(/Classes/Pokemon.php
/**
* 残りHP
* @var integer
*/
protected $remaining_hp;

 

こちらも取得用のメソッドとしてGet格納トレイトにgetRemainingHpを作成しておいてください

 

プロパティを作成したら、引き継ぎ処理にも追加しておきましょう。今回引き継ぎ処理を簡易化させました。

 

ポケモンクラス(/Classes/Pokemon.php
/**
* 現在インスタンスを出力(引き継ぎ用)
*
* @return array
*/
public function export()
{
    return [
        'class_name' => get_class($this),       # クラス名
        'nickname' => $this->nickname,          # ニックネーム
        'level' => $this->level,                # レベル
        'ev' => $this->ev,                      # 努力値
        'iv' => $this->iv,                      # 個体値
        'exp' => $this->exp,                    # 経験値
        'move' => $this->move,                  # 技
        'sa' => $this->sa,                      # 状態異常
        'remaining_hp' => $this->remaining_hp,  # 残りHP
    ];
}
 
/**
* 能力引き継ぎ処理
*
* @param array $before
* @return void
*/
protected function takeOverAbility($before)
{
    foreach($before as $key => $val){
        $this->$key = $val;
    }
}

 

exportには追加になった残りHPの項目を増やしています。

能力引き継ぎの処理についてですが、それぞれ値を指定するのではなく、foreachで回していきながらそれぞれキー通りのプロパティに設定するという仕様です。進化時の引き継ぎ処理としてオブジェクトの分岐をしていましたが、こちらはオブジェクトではなくexportした配列を引数として渡す仕様に、ポケモンのコンストラクタ内を変更しました。

 

ポケモンクラス(/Classes/Pokemon.php__construct内)
/**
* 進化した際の処理
* @var object $before
*/
case 'object':
// 進化前のポケモンと一致しているかチェック
if(is_a($before, $this->before_class ?? null)){
    $this->takeOverAbility($before->export());
    // メッセージの引き継ぎ
    $this->setMessage($before->getMessages());
    $this->setMessage($this->name.'に進化した', 'success');
    $this->checkMove();
}
break;

 

計算用メソッドの作成

 次に、計算用のメソッドを作成しましょう。上限値と下限値が決まっているため、原則としては直接プロパティに値をセットするようなことはしません。

計算用メソッドもポケモンクラスで使用しますが、addRanksubRankなど計算系のメソッドが多くなってきたので、新しく計算用メソッドの格納トレイトを作成しましょう。

 

計算用トレイト(/Traits/Pokemon/CalculationTrait.php
<?php
trait CalculationTrait
{
 
    /**
    * ランクの加算
    *
    * @param string $param
    * @param integer $val (min:1, max:12)
    * @return string
    */
    public function addRank($param, $val)
    {
        // 変化ランクに合わせたメッセージ
        $msg = [
            1 => '上がった',
            2 => 'ぐーんと上がった',
            3 => 'ぐぐーんと上がった',
            12 => '最大まで上がった',
        ];
        // 既にランクが最大であればfalseを返却
        if($this->rank[$param] === 6){
            return $this->name.'の'.transJp($param).'はもう上がらない';
        }
        // 加算処理
        $this->rank[$param] += $val;
        // 最大値は6
        if($this->rank[$param] > 6){
            $this->rank[$param] = 6;
        }
        return $this->name.'の'.transJp($param).'が'.$msg[$val] ?? $msg[3];
    }
 
    /**
    * ランクの減算
    *
    * @param string $param
    * @param integer $val (min:1, max:3)
    * @return string
    */
    public function subRank($param, $val)
    {
        // 変化ランクに合わせたメッセージ
        $msg = [
            1 => '下がった',
            2 => 'がくっと下がった',
            3 => 'がくーんと下がった',
        ];
        // 既にランクが最低であればfalseを返却
        if($this->rank[$param] === -6){
            return $this->name.'の'.transJp($param).'はもう下がらない';
        }
        // 減算処理
        $this->rank[$param] -= $val;
        // 最低値は-6
        if($this->rank[$param] < -6){
            $this->rank[$param] = -6;
        }
        return $this->name.'の'.transJp($param).'が'.$msg[$val] ?? $msg[3];
    }
 
    /**
    * 残りHPの計算
    *
    * @param string $param
    * @param integer $val (default:0)
    * @return integer
    */
    public function calRemainingHp($param, $val=0)
    {
        switch ($param) {
            // リセット処理
            case 'reset':
            // 最大HPをセット
            $this->remaining_hp = $this->getStats('HP');
            if(isset($this->sa['SaFainting'])){
                // ひんしの場合は解除
                unset($this->sa['SaFainting']);
            }
            break;
            // 即死処理
            case 'death':
            $this->remaining_hp = 0;
            break;
            // 減算処理
            case 'sub':
            $this->remaining_hp -= $val;
            break;
            // 加算処理
            case 'add':
            $this->remaining_hp += $val;
            // 最大HPを超えないようにする
            if($this->remaining_hp > $this->getStats('HP')){
                $this->remaining_hp = $this->getStats('HP');
            }
            break;
        }
        // HPが0以下になった場合の処理
        if($this->remaining_hp <= 0){
            // 状態異常をひんしに書き換え
            $this->sa = ['SaFainting' => ''];
            $this->remaining_hp = 0;
        }
        // 残りHPを返却
        return $this->remaining_hp;
    }
}

 

作成したトレイトはポケモンクラスで読み込んでおいてください

 

それでは新しく追加した、calRemainingHpのメソッドを見ていきましょう。

/**
* 残りHPの計算
*
* @param string $param
* @param integer $val (default:0)
* @return integer
*/
public function calRemainingHp($param, $val=0)

 

第1引数でどういった計算をするかを指定します。今回準備したのは初期化(reset)即死(death)減算(sub)加算(add)の4つです。

第2引数にはが入ります。subであればダメージ量addであれば回復量です。

 

次に処理内の分岐を見ていきましょう。

switch ($param) {
    // リセット処理
    case 'reset':
    // 最大HPをセット
    $this->remaining_hp = $this->getStats('HP');
    if(isset($this->sa['SaFainting'])){
        // ひんしの場合は解除
        unset($this->sa['SaFainting']);
    }
    break;
    // 即死処理
    case 'death':
    $this->remaining_hp = 0;
    break;
    // 減算処理
    case 'sub':
    $this->remaining_hp -= $val;
    break;
    // 加算処理
    case 'add':
    $this->remaining_hp += $val;
    // 最大HPを超えないようにする
    if($this->remaining_hp > $this->getStats('HP')){
        $this->remaining_hp = $this->getStats('HP');
    }
    break;
}

 

第1引数で受け取った$paramの値に対して分岐をかけていきます。

最初の初期化(reset)処理は、ポケモン生成時や全回復をする際に使用します。現在は用意されていませんが、ポケモンセンターやボックスへ入れて再度取り出すなどした際、「かいふくのくすり」などを選択した際に使用する予定です。

// リセット処理
case 'reset':
// 最大HPをセット
$this->remaining_hp = $this->getStats('HP');
break;

 

2つ目の即死(death)処理は、一撃必殺などダメージに関係なくHPを0にする際に使用します。

// 即死処理
case 'death':
$this->remaining_hp = 0;
break;

 

3つ目の処理は減算(sub)処理です。ダメージを受けた際に使用します。数値がマイナスになれば0に戻すという処理をしなければなりませんが、この処理内では行わずに最終的に処理します。

// 減算処理
case 'sub':
$this->remaining_hp -= $val;
break;

 

4つ目の処理は加算(add)処理です。アイテムによる回復や「じこさいせい」など回復技による処理を行う際に使用します。

// 加算処理
case 'add':
$this->remaining_hp += $val;
// 最大HPを超えないようにする
if($this->remaining_hp > $this->getStats('HP')){
    $this->remaining_hp = $this->getStats('HP');
}
break;

 

最大HPを超えてしまわないように、加算後に数値のチェックを行なっています。

 

次に分岐後の共通処理について見ていきましょう。

// 復活判定(ひんしからの回復)
if(isset($this->sa['SaFainting']) && ($this->remaining_hp > 0)){
    unset($this->sa['SaFainting']);
}
// ひんし判定
if($this->remaining_hp <= 0){
    // 状態異常をひんしに書き換え
    $this->sa = ['SaFainting' => null];
    $this->remaining_hp = 0;
}
// 残りHPを返却
return $this->remaining_hp;

 

まず最初に、復活判定を行います。もしひんし状態からの回復がなされた場合、状態異常にセットしている「ひんし」を解除しなければなりません。これはresetaddのどちらかで必要になるため、分岐後にチェックしています。

 

次に、HPが0になった場合のひんし判定を行います。もし残りHPが0以下であれば、状態異常をひんし(SaFainting)に上書きをして、残りHPに対して0をセットしました。こうすることで、マイナスの値が入ることはありません。

 

最後に返り値として残りHPを返却します。こちらは使用しないこともありますが、ダメージ判定後にHPがどうなったかを確認する際に活用できるように指定しました。

 

ダメージ計算

 それではダメージ計算に対して、作成した残りHPの減算処理を実装しましょう。

 

バトルコントローラー(/Classes/Controller/BattleController.php
/**
* アクション
*
* @param string $action
* @param mixed $param
* @return void
*/
private function action($action, $param)
{
    // 敵ポケモンの技をインスタンス化
    $e_move = $this->getInstance($this->aiSelectMove());
    switch ($action) {
        /**
        * にげる
        */
        case 'run':
        // $this->run++;
        if($this->checkRun()){
            unset($_SESSION['enemy']);
            unset($_SESSION['rank']);
            unset($_SESSION['run']);
            header("Location: ./home.php", true, 307);
            exit;
        }
        $this->setMessage('逃げられない!');
        // 敵ポケモンの攻撃
        $p_damage = $this->attack($this->enemy, $this->pokemon, $e_move);
        break;
        /**
        * たたかう
        */
        case 'fight':
        // 自ポケモンの技をインスタンス化
        $p_move = $this->getInstance($param);
        // 行動順の判定
        if($this->checkFirstMove($p_move, $e_move)){
            // 先行
            // 自ポケモンの攻撃
            $e_damage = $this->attack($this->pokemon, $this->enemy, $p_move);
            $this->enemy
            ->calRemainingHp('sub', $e_damage);
            // 敵ポケモンの攻撃
            $p_damage = $this->attack($this->enemy, $this->pokemon, $e_move);
            $this->pokemon
            ->calRemainingHp('sub', $p_damage);
        }else{
            // 後攻
            // 敵ポケモンの攻撃
            $p_damage = $this->attack($this->enemy, $this->pokemon, $e_move);
            $this->pokemon
            ->calRemainingHp('sub', $p_damage);
            // 自ポケモンの攻撃
            $e_damage = $this->attack($this->pokemon, $this->enemy, $p_move);
            $this->enemy
            ->calRemainingHp('sub', $e_damage);
        }
        break;
    }
}

 

それぞれダメージ計算終了後に残りHPの減算処理を行なっています。変化技などを使いダメージが0であれば0の減算が行われることになります。

実際のバトルでは、HPが0になった時点でバトルが終了しますが、バトル終了のアクション自体がまだ出来ていないので、一旦このままで進めていきましょう。

 

現状はHPの回復手段がありません。なので、もしHPが0でバトルが終了すれば全回復するようにホーム画面のコントローラーに簡易策としてリセット処理を入れておきましょう。

 

ホームコントローラー(/Classes/Controller/HomeController.php
/**
* アクション
*
* @param string $action(method_name)
* @param mixed $param
* @return void
*/
private function action($action, $param)
{
    // リセットの処理
    if($action === 'reset' || is_null($this->pokemon)){
        header("Location: ./index.php", true, 307) ;
        exit;
    }
    // にげるの処理
    if($action === 'run'){
        $this->setMessage('逃げ切れた', 'success');
        if($this->pokemon->getRemainingHp() <= 0){
            // ひんし状態ならHPを全回復させる
            $this->pokemon
            ->calRemainingHp('reset');
        }
        return;
    }
    // 呼び出せるメソッドか判別
    if(is_callable([$this->pokemon, $action])){
        // メソッド実行結果を$resultに格納
        $result = $this->pokemon
        ->$action($param);
        switch ($action) {
            // 経験値の取得
            case 'setExp':
            $this->pokemon = $result;
            break;
        }
        // Pokemonクラスに溜まったメッセージを取得
        $this->setMessage($this->pokemon->getMessages());
    }else{
        $this->setMessage('このアクションは使用できません', 'error');
    }
}

 

レベルアップ・進化時の残りHP

 次にレベルアップ、進化時の残りHPの計算処理を実装します。

ポケモンではレベルアップすれば、HPの上昇値に合わせてHPが回復します。これは進化した際も同じです。こうすることで、レベルアップしたのにHPが減っているという現象を防ぐことができます。

 

ポケモンクラス(/Classes/Pokemon.php
/**
* レベルアップ処理
*
* @return void
*/
protected function actionLevelUp()
{
    // 現在のHPを取得
    $before_hp = $this->getStats('HP');
    // レベルアップ
    $this->level++;
    // HPの上昇値分だけ残りHPを加算(ひんし状態を除く)
    if(!isset($this->sa['SaFainting'])){
        $this->calRemainingHp('add', $this->getStats('HP') - $before_hp);
    }
    $this->setMessage($this->getNickName().'のレベルは'.$this->level.'になった!', 'success');
    // 現在のレベルで習得できる技があるか確認
    $this->checkMove();
}
 
/**
* 進化
*
* @return Classes\Pokemon\$after_class
*/
protected function evolve()
{
    if(class_exists($this->after_class ?? null)){
        // 現在のHPを取得
        $before_hp = $this->getStats('HP');
        // 進化ポケモンのインスタンスを生成
        $pokemon = new $this->after_class($this);
        // HPの上昇値分だけ残りHPを加算(ひんし状態を除く)
        if(!isset($pokemon->sa['SaFainting'])){
            $pokemon->calRemainingHp('add', $pokemon->getStats('HP') - $before_hp);
        }
        // 進化後のインスタンスを返却
        return $pokemon;
    }else{
        $this->setMessage('このポケモンは進化できません', 'error');
    }
}

 

レベルアップまたは進化前に現在の最大HPを取得し、その後のステータスとの差分を算出しcalRemainingHpで加算処理を行なっています。ただし例外として、ひんし状態であれば加算処理は不要です。ひんし状態でのレベルアップは「ふしぎなアメ」などアイテムを使った際に起こりますが、これによる復活処理を回避するためです。

※初代では復活した覚えがありますがうろ覚えです

 

rangeを使ったビジュアル

 最後にビジュアルを作成して残りHPがどれぐらいあるかを確認できるようにしましょう。CSSで作る予定でしたがinputのrangeが使えるということに気づいてしまったので、こちらを代用します。

input range(HTMLクイックリファレンス)

 

バトル画面(/battle.php
<section>
    <div class="row mt-3 mb-5">
        <?php # 敵ポケモン詳細 ?>
        <div class="col-6">
            <p><?=$enemy->getName()?> Lv:<?=$enemy->getLevel()?></p>
            <p><?=$enemy->getSaName()?></p>
            <div class="form-group">
                <input type="range" class="form-control-range" min="0" max="<?=$enemy->getStats('HP')?>" value="<?=$enemy->getRemainingHp()?>" style="pointer-events: none;">
            </div>
        </div>
        <div class="col-6 text-center">
            <img src="Resources/Assets/img/pokemon/dots/front/<?=get_class($enemy)?>.gif" alt="<?=$enemy->getName()?>">
        </div>
    </div>
    <div class="row mb-3">
        <?php # 自ポケモン詳細 ?>
        <div class="col-6 text-center">
            <img src="Resources/Assets/img/pokemon/dots/back/<?=get_class($pokemon)?>.gif" alt="<?=$pokemon->getName()?>">
        </div>
        <div class="col-6">
            <p><?=$pokemon->getName()?> Lv:<?=$pokemon->getLevel()?></p>
            <p><?=$pokemon->getSaName()?></p>
            <div class="form-group">
                <input type="range" class="form-control-range" min="0" max="<?=$pokemon->getStats('HP')?>" value="<?=$pokemon->getRemainingHp()?>" style="pointer-events: none;">
                <p class="text-right px-3"><?=$pokemon->getRemainingHp()?> / <?=$pokemon->getStats('HP')?></p>
            </div>
        </div>
    </div>
</section>

 

それでは出力結果を見てみましょう。

 

 

 

持ち手が邪魔ですがほぼ完璧です。

ポケモンでは残りHPが1/2、1/4と減っていくことでゲージの色が変わりますが、そのあたりは後ほど対応します。HPバーは変更されても数値に影響はないので構いませんが、念の為pointer-eventsを使って無効化しました。

 

rangeのminに0maxに最大HPvalueに残りHPをセットするだけで自動計算してくれるという仕組みです。ちなみにですが、ひんし設定はしていますが判定はしていないので、現状お互い死んでも殴り続けることができるというサイコなゲームとなっています。

  

まとめ

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

今回のPHPポケモンは「バトルシステム編〜HP計算〜」についてご紹介しました。

ポケモン好きな人やゲームづくりに興味がある人、現在プログラミング学習に取り組んでいる人は、ぜひ参考にしてみてくださいね。

 

注目の記事

投稿タイトルを自動生成する方法【WordPressを便利にカスタマイズ】
プログラミング
PHP,WordPress
投稿タイトルを自動生成する方法【WordPressを便利にカスタマイズ】

  カスタムフィールドを含む投稿の場合、わざわざタイトルを設定する必要がないものもあります。 そういったときに、カスタムフィールド値を使ってタイトルを自動生成してくれると楽ですし、一覧で見てもわかりやすい状態にすることができます。   今回はWordPressで「投稿タイトルを自動生成する方法」につ...

【変数とは】初心者が最短でPHPを使えるようになるための実践的な学び方
プログラミング
HTML,PHP,プログラミング学習
【変数とは】初心者が最短でPHPを使えるようになるための実践的な学び方

  ※PHP初心者へ向けた内容となりますので、ある程度HTMLの知識がある方を対象とした内容になります。予めご了承ください。    Webプログラミングを学ぶ方はHTML、そしてCSSを学び、そしてJavascriptやPHPという順に学んでいくひとが多いでしょう。 私も実際に、似たような手順で学んでいきました。   ...

AIが人類にもたらす驚異!深層学習が与える影響とは
ネットワーク
AI,ディープフェイク,深層学習
AIが人類にもたらす驚異!深層学習が与える影響とは

  海外の記事でAIについて記述した興味深いものが掲載されました。   今回は「AIが人類にもたらす驚異!深層学習が与える影響とは」について、上記サイトを参考にまとめましたのでご紹介します。 ※直訳ではありません、あくまで記事の内容を参考にして自らの考えを記述したものです     AIの驚異と...

PHPポケモン「行動順判定+敵ポケモン攻撃編」25
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「行動順判定+敵ポケモン攻撃編」25

行動順の判定 ポケモンの行動順は以下の通りです。 技の優先度 すばやさの実数値(補正有り) 同速の場合は50%の乱数   この順番で比較を行い、先行後攻を決めます。ただし、これは両者ともに攻撃を選択した場合のみです。アイテムの使用や交代は技よりも優先されますし(※一部技を除く)、にげる...

SNSだけじゃダメ!PV数アップのためにSEO対策する理由とは
SEO対策
Twitter
SNSだけじゃダメ!PV数アップのためにSEO対策する理由とは

  「SNSで集客しているけど中々伸びなくなってきた」 「たまにPV数がアップするけど安定しない」 「本当に月何十万も稼げるぐらいPVは伸びるの?」   PV数を稼ぐためにSNSを駆使したり、中には広告を使って集客しているサイトもあるでしょう。ですが、それだけでは疲弊しながらユーザーを獲得しているに...

ポケモン図鑑編 PHPポケモン 88
プログラミング
PHP,PHPポケモン,ポケモン
ポケモン図鑑編 PHPポケモン 88

ポケモン図鑑とは ポケモンに出会ったり、仲間にしたりすると、ポケモン図鑑のデータがどんどんと埋まっていきます。PHPポケモンでもこの仕組みを実現させるために、ポケモン図鑑を作成していきましょう。   クラスによる管理 ポケモン図鑑はクラス管理をしていきます。プレイヤー1人に対して1つのポケモン図...

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

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

進化直後の技習得編 PHPポケモン 65
プログラミング
PHP,PHPポケモン,ポケモン
進化直後の技習得編 PHPポケモン 65

進化直後の技習得 パーティー機能を導入に合わせて、至る場所を修正することになり、合わせて未実装だった機能を導入していきます。 見た目にはわからない部分や、とある条件が重ならなければ起こらない部分の作り込みが多いため、プレイユーザー目線からすると少し面白みが無いかも知れません。 ですが、そういっ...

カテゴリ

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