プログラミング

PHPポケモン「バトルシステム編〜状態変化〜」32

PHP PHPポケモン ポケモン
PHPポケモン「バトルシステム編〜状態変化〜」32

状態変化とは

 状態異常の実装が完了したので、いよいよ状態変化の実装に移ります。PHPポケモンで実装する状態変化とは以下の4つです。

  1. こんらん
  2. ひるみ
  3. バインド
  4. やどりぎのタネ

 

上記4つを実装していきます。状態異常と異なり、技によっては追加になる可能性があります

※いかり状態など

 

状態異常と異なる点は、バトル終了とともに解除されるということと、複数の状態変化が併用できるという点です。

また、こちらも状態異常と同じく攻撃前と攻撃後、どちらかの判定に属することになりますので、そちらも踏まえながら1つずつ説明と実装をしていきます。

 

まずは状態変化の親クラスとなるStateChangeを作成します。

 

状態変化(/Classes/StateChange.php
<?php
 
// 状態変化
abstract class StateChange
{
 
    /**
    * インスタンス作成時に実行される処理
    *
    * @return void
    */
    public function __construct()
    {
        //
    }
 
    /**
    * 名称の取得
    *
    * @return string
    */
    public function getName()
    {
        return $this->name;
    }
 
    /**
    * 状態変化にかかった際のメッセージを取得
    *
    * @param string $pokemon
    * @return string
    */
    public function getSickedMessage($pokemon, $param='Standard')
    {
        if(is_array($this->sicked_msg)){
            return str_replace('::pokemon', $pokemon, $this->sicked_msg[$param]);
        }else{
            return str_replace('::pokemon', $pokemon, $this->sicked_msg);
        }
 
    }
 
    /**
    * 既に状態変化にかかっている際のメッセージを取得
    *
    * @param string $pokemon
    * @return string
    */
    public function getSickedAlreadyMessage($pokemon, $param='Standard')
    {
        if(is_array($this->sicked_already_msg)){
            return str_replace('::pokemon', $pokemon, $this->sicked_already_msg[$param]);
        }else{
            return str_replace('::pokemon', $pokemon, $this->sicked_already_msg);
        }
 
    }
 
    /**
    * 状態変化にかかった際のメッセージを取得
    *
    * @param string $pokemon
    * @return string
    */
    public function getTurnMessage($pokemon, $param='Standard')
    {
        if(is_array($this->turn_msg)){
            return str_replace('::pokemon', $pokemon, $this->turn_msg[$param]);
        }else{
            return str_replace('::pokemon', $pokemon, $this->turn_msg);
        }
 
    }
 
    /**
    * 行動失敗時のメッセージを取得
    *
    * @param string $pokemon
    * @return string
    */
    public function getFalseMessage($pokemon, $param='Standard')
    {
        if(is_array($this->false_msg)){
            return str_replace('::pokemon', $pokemon, $this->false_msg[$param]);
        }else{
            return str_replace('::pokemon', $pokemon, $this->false_msg);
        }
    }
 
    /**
    * 回復時のメッセージを取得
    *
    * @param string $pokemon
    * @param string $param
    * @return string
    */
    public function getRecoveryMessage($pokemon, $param='Standard')
    {
        if(is_array($this->recovery_msg)){
            return str_replace('::pokemon', $pokemon, $this->recovery_msg[$param]);
        }else{
            return str_replace('::pokemon', $pokemon, $this->recovery_msg);
        }
    }
 
}

 

状態異常とほとんど同じ内容ですが、メッセージを取り出す際に配列かどうかをチェックしている点が異なります。こちらは後ほど説明します。

 

次に、ポケモンに対して状態変化を格納するためのプロパティ(sc)を用意しましょう。

 

ポケモンクラス(/Classes/Pokemon.php
/**
* 状態変化(バトル後リセット)
* ScConfusion           こんらん
* ScFlinch              ひるみ
* ScLeechSeed           やどりぎのタネ
* ScBind                バインド
* @var array [sc_class_name(string) => ['turn' => turn(integer), 'param' => param(string)]]
*/
protected $sc = [];

状態異常ではクラス名をキーにしてターン数が値として格納されていましたが、状態変化では配列を値として格納して、その中にturnparamのキーに割り当てられた値を持っています。ターンには経過または残ターン数が入ります。paramについては、今回実装する中ではバインド状態で使用します。

 

次にチェック用のメソッドを作成しましょう。

 

チェック格納トレイト(/Traits/Battle/CheckTrait.php
/**
* アタック前の状態変化チェック
*
* @param object Pokemon
* @return boolean
*/
protected function checkBeforeSc($pokemon)
{
    $sc = $pokemon->getSc();
    if(empty($sc)){
        // 状態変化にかかっていない
        return true;
    }
 
    // ここに分岐
 
    // 行動可
    return true;
}
 
 
/**
* アタック後の状態変化チェック
*
* @param object Pokemon
* @return boolean (false:ひんし)
*/
protected function checkAfterSc($sicked_pokemon, $enemy_pokemon)
{
    // 状態変化を取得
    $sc = $sicked_pokemon->getSc();
    if(empty($sc)){
        // 状態異常にかかっていない
        return true;
    }
 
    // ここに分岐
 
    // ひんし状態ではない
    return true;
}

 

行動前のチェックでは状態異常同様に引数で対象ポケモンのインスタンスを受け取っていますが、行動後では第2引数で相手ポケモン(状態変化をかけた側)のインスタンスを受け取っておきます。これは、やどりぎのタネで回復処理が必要になるためです。

 

ポケモンインスタンスから呼び出しているgetScのメソッドについてですが、こちらは単純に状態変化すべてを返却しています。

 

Get格納トレイト(Traits/Pokemon/GetTrait.php
/**
* 現在の状態変化を取得する
* @return array
*/
public function getSc()
{
    return $this->sc;
}

 

最後に、作成したチェック関数をそれぞれ状態異常と同じタイミングで呼び出しておきましょう。

 

攻撃用トレイト(/Traits/Battle/AttackTrait.php
/**
* 攻撃
* (攻撃→ダメージ計算→ひんし判定)
*
* @param object $atk_pokemon
* @param object $def_pokemon
* @param object $move
* @return boolean (true:相手を戦闘不能にした)
*/
protected function attack($atk_pokemon, $def_pokemon, $move)
{
    // 行動チェック(状態異常・状態変化)
    if(!$this->checkBeforeSa($atk_pokemon) || !$this->checkBeforeSc($atk_pokemon)){
        // 行動失敗
        return;
    }

 

バトルコントローラー(/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()){
            $this->endBattle();
        }
        $this->setMessage('逃げられない!');
        // 敵ポケモンの攻撃
        $p_damage = $this->attack($this->enemy, $this->pokemon, $e_move);
        break;
        /**
        * たたかう
        */
        case 'fight':
        // 自ポケモンの技をインスタンス化
        $p_move = $this->getInstance($param);
        // 行動順の判定
        $order_array = $this->orderMove(
            [$this->pokemon, $this->enemy, $p_move],
            [$this->enemy, $this->pokemon, $e_move],
        );
        // 行動順にforeachでattackメソッドを実行
        foreach($order_array as list($atk, $def, $move)){
            if($this->attack($atk, $def, $move)){
                // 相手をひんし状態にした
                break;
            }
        }
        // 行動順にforeachでcheckAfterSaとcheckAfterScを実行
        foreach($order_array as list($atk, $def, $move)){
            if(!$this->checkAfterSa($atk) || !$this->checkAfterSc($atk, $def)){
                // ひんし状態になった
                break;
            }
        }
        $this->setMessage('行動を選択してください');
        break;
    }
}

 

これで状態変化の下準備は完了です。それではそれぞれの状態変化に合わせた処理と分岐を作成していきましょう。

  

こんらん

 まずは「こんらん」についてです。おなじみポケモンWikiを参考にします。

14ターン(第一世代では17ターン)の間、1/3(第六世代までは1/2)の確率で威力40の物理攻撃を自分にする。ただし、反動で動けない間や、ねむり、こおり、ひるみ、なまけなどになっているターンはカウントせず、自分への攻撃も起こらない。

こんらん(ポケモンwiki

 

ねむりと同様に、状態変化をセットする際にターン数をセットして、毎ターン残数を引いていきます。眠りとは異なり、失敗時には「自らを攻撃する」という処理が入るため、ダメージ計算とひんし判定が必要になります。

 

まずはこんらんのクラスを作成します。

 

こんらん(/Classes/StateChange/ScConfusion.php
<?php
require_once(__DIR__.'/../StateChange.php');
 
// こんらん
class ScConfusion extends StateChange
{
 
    /**
    * 正式名称
    * @var string
    */
    protected $name = 'こんらん';
 
    /**
    * 状態変化にかかった際のメッセージ
    * @var string
    */
    protected $sicked_msg = '::pokemonは、混乱した';
 
    /**
    * すでにこの状態変化にかかっている際のメッセージ
    * @var string
    */
    protected $sicked_already_msg = '::pokemonは、既に混乱している';
 
    /**
    * ターンチェック時に表示されるメッセージ
    * @var string
    */
    protected $turn_msg = '::pokemonは、こんらんしている';
 
    /**
    * 行動失敗
    * @var string
    */
    protected $false_msg = '::pokemonは、わけも分からず自分を攻撃した';
 
    /**
    * 回復時に表示されるメッセージ
    * @var string
    */
    protected $recovery_msg = '::pokemonはこんらんが解けた';
 
}

 

次にこんらんのチェックを作成します。こんらんは行動前に判定が行われるため、checkBeforeScに分岐を記述しましょう。

 

チェック格納トレイト(/Traits/Battle/CheckTrait.php
/**
* こんらん
*/
if(isset($sc['ScConfusion'])){
    $confusion = new ScConfusion;
    // こんらんのターンカウントを進める
    $pokemon->goScTurn('ScConfusion');
    if($sc['ScConfusion']['turn'] <= 0){
        // こんらん解除
        $pokemon->releaseSc('ScConfusion');
        $this->setMessage($confusion->getRecoveryMessage($pokemon->getPrefixName()));
    }else{
        // こんらんしている旨のメッセージ
        $this->setMessage($pokemon->getPrefixName().'は混乱している');
        // 1/3の確率で行動失敗
        if(!random_int(0, 2)){
            // 行動失敗(自分に威力40の物理ダメージ)
            $this->setMessage($confusion->getFalseMessage($pokemon->getPrefixName()));
            // ダメージ計算
            $damage = $this->calDamage(
                $pokemon->getLevel(),                   # レベル
                $pokemon->getStats('Attack', true),     # 物理攻撃値(補正値込み)
                $pokemon->getStats('Defense', true),    # 物理防御値(補正値込み)
                40, # 技の威力
                1,  # 補正値
            );
            // ダメージ計算
            $pokemon->calRemainingHp('sub', $damage);
            // ひんしチェック
            $this->checkFainting($pokemon);
            return false;
        }
    }
}

 

処理の最初にターンカウントを進め、カウントが0以下であれば混乱を解除しています。もし解除されていなければ、そこから更に分岐が入ります。1/3の確率で失敗の判定となるため、random_intで0〜2の乱数をとり、0(false)であれば攻撃失敗という仕組みです。

 

状態変化を解除するためのreleaseScはポケモンクラスに作成しておきましょう。

 

ポケモンクラス(/Classes/Pokemon.php
/**
* 状態変化の解除
*
* @param string $class
* @return void
*/
public function releaseSc($class)
{
    unset($this->sc[$class]);
}

  

自傷攻撃

 こんらんの行動失敗判定は、威力40の物理攻撃を自身に行うというものです。なので、ここで自身に対してダメージ計算を行なっています。

// 行動失敗(自分に威力40の物理ダメージ)
$this->setMessage($confusion->getFalseMessage($pokemon->getPrefixName()));
// ダメージ計算
$damage = $this->calDamage(
    $pokemon->getLevel(),                   # レベル
    $pokemon->getStats('Attack', true),     # 物理攻撃値(補正値込み)
    $pokemon->getStats('Defense', true),    # 物理防御値(補正値込み)
    40, # 技の威力
    1,  # 補正値
);
// ダメージ計算
$pokemon->calRemainingHp('sub', $damage);
// ひんしチェック
$this->checkFainting($pokemon);
return false;

 

これで分岐が完成しました。こんらん状態は「あやしいひかり」を使って検証しましょう。

 

あやしいひかり(/Classes/Move/ConfuseRay.php
<?php
require_once(__DIR__.'/../Move.php');
 
// あやしいひかり
class ConfuseRay extends Move
{
 
    /**
    * 正式名称
    * @var string
    */
    protected $name = 'あやしいひかり';
 
    /**
    * 説明文
    * @var string
    */
    protected $description = '相手をこんらん状態にする。';
 
    /**
    * タイプ
    * @var string
    */
    protected $type = 'Ghost';
 
    /**
    * 分類
    * @var string(physical:物理|special:特殊|status:変化)
    */
    protected $species = 'status';
 
    /**
    * 威力
    * @var integer
    */
    protected $power = null;
 
    /**
    * 命中率
    * @var integer
    */
    protected $accuracy = 100;
 
    /**
    * 使用回数
    * @var integer
    */
    protected $pp = 10;
 
    /**
    * 優先度
    * @var integer
    */
    protected $priority = 0;
 
    /**
    * 追加効果
    *
    * @param array $args
    * @return void
    */
    public function effects(...$args)
    {
        /**
        * @param Pokemon $atk 攻撃ポケモン
        * @param Pokemon $def 防御ポケモン
        */
        list($atk, $def) = $args;
        // 相手をこんらん状態にする
        $msg = $def->setSc('ScConfusion', random_int(1, 4));
        // メッセージをセット
        $this->setMessage($msg);
    }

}

 

ポケモンメソッドに対して使用しているsetScは以下の通りです。

 

Set格納トレイト(/Traits/Pokemon/SetTrait.php
/**
* 状態変化をセットする
* @param string|array $class
* @param integer $turn
* @param string $param
* @return string
*/
public function setSc($class, $turn=0, $param='Standard')
{
    // 状態変化の引き継ぎ処理
    if(is_array($class)){
        $this->sc = $class;
        return;
    }
    // セットできる状態異常一覧
    $sc_list = [
        'ScConfusion', 'ScFlinch', 'ScLeechSeed', 'ScBind',
    ];
    // クラスチェック
    if(!in_array($class, $sc_list, true) || !class_exists($class)){
        // 不正なクラス
        return '指定された状態変化は存在しません';
    }
    $sc = new $class;
    // 状態変化のセット確認
    if(isset($this->sc[$class])){
        // 既に同じ状態変化にかかっている
        return $sc->getSickedAlreadyMessage($this->getPrefixName(), $param);
    }else{
        // 状態変化をセット
        $this->sc[$class] = [
            'turn' => $turn,
            'param' => $param,
        ];
        return $sc->getSickedMessage($this->getPrefixName(), $param);
    }
}

 

setSaと似た処理になりますが、こちらは複数を許可しています。また、paramの項目がある関係上、第3引数でparamの値を指定できる仕様になっています。

 

以下、出力結果です。

 

 

 

 

 

 

 

ひるみ

 次に「ひるみ」を実装しましょう。こちらもポケモンwikiを参考にしていきます。

そのターンのみ、行動できなくなる。

ひるみ(ポケモンwiki

 

ひるみ状態のクラスは以下の通りです。

 

ひるみ(/Classes/StateChange/ScFlinch.php
<?php
require_once(__DIR__.'/../StateChange.php');
 
// ひるみ
class ScFlinch extends StateChange
{
 
    /**
    * 正式名称
    * @var string
    */
    protected $name = 'ひるみ';
 
    /**
    * 状態変化にかかった際のメッセージ
    * @var string
    */
    protected $sicked_msg = '::pokemonは、ひるんだ';
 
}

 

こちらも行動の有無に関わる状態変化のため、行動前(checkBeforeSc)のメソッドに判定を追加しましょう。

 

チェック格納トレイト(/Traits/Battle/CheckTrait.php
/**
* ひるみ
*/
if(isset($sc['ScFlinch'])){
    $flinch = new ScFlinch;
    // 行動失敗
    return false;
}
 
/**
* こんらん
*/

 

ここで注意すべき点は、こんらんの前に記述するということです。その理由は、こんらんにあります。

ただし、反動で動けない間や、ねむり、こおり、ひるみ、なまけなどになっているターンはカウントせず、自分への攻撃も起こらない。

 

これは、ひるんでいればこんらんの判定自体が行われないことになります。なので、ひるみの判定はこんらんよりも先に実行します。

 

解除タイミング

 ひるみは1ターン限りの状態変化です。なので、状態異常をセットした後にはそのターンの最後に解除する必要があります。なので、checkAfterScに解除処理を追加しましょう。

/**
* アタック後の状態変化チェック
*
* @param object Pokemon
* @return boolean (false:ひんし)
*/
protected function checkAfterSc($sicked_pokemon, $enemy_pokemon)
{
    // ひるみ解除
    $sicked_pokemon->releaseSc('ScFlinch');

 

 それでは「かみつく」を使って出力結果を見てみましょう。

 

かみつく(/Classes/Move/Bite.php
<?php
require_once(__DIR__.'/../Move.php');
 
// かみつく
class Bite extends Move
{
 
    /**
    * 正式名称
    * @var string
    */
    protected $name = 'かみつく';
 
    /**
    * 説明文
    * @var string
    */
    protected $description = '30%の確率で敵をひるませる。';
 
    /**
    * タイプ
    * @var string
    */
    protected $type = 'Dark';
 
    /**
    * 分類
    * @var string(physical:物理|special:特殊|status:変化)
    */
    protected $species = 'physical';
 
    /**
    * 威力
    * @var integer
    */
    protected $power = 60;
 
    /**
    * 命中率
    * @var integer
    */
    protected $accuracy = 100;
 
    /**
    * 使用回数
    * @var integer
    */
    protected $pp = 25;
 
    /**
    * 優先度
    * @var integer
    */
    protected $priority = 0;
 
    /**
    * 追加効果
    *
    * @param array $args
    * @return void
    */
    public function effects(...$args)
    {
        // 30%の確率
        if(30 < random_int(0, 100)){
            // random_intで31以上が生成されたら失敗
            return;
        }
        /**
        * @param Pokemon $atk 攻撃ポケモン
        * @param Pokemon $def 防御ポケモン
        */
        list($atk, $def) = $args;
        // 相手をひるませる
        $msg = $def->setSc('ScFlinch');
        // メッセージをセット
        $this->setMessage($msg);
    }

}

 

 

 

 

バインド

 次に「バインド」状態の状態変化を作成します。こちらは聞き慣れないひとが多いかも知れませんが、「まきつく」や「しめつける」などの技を使った際に用いられる縛り状態の状態変化です。

バインドとは、ポケモンの状態変化の一つ。

第六世代までは、しめつける状態と呼ばれていた。

 

交代や逃げることができなくなる。

テレポートで戦闘を終わらせることができない。第八世代からはプレイヤーがテレポートを使用する場合はバインド状態でも交代することができるが、野生ポケモンがテレポートを使用する場合は失敗する。

ターンごとにダメージを受ける。

第五世代までは、最大HP1/16

第六世代からは、最大HP1/8

最後のターンは解除メッセージのみでダメージは受けない(第三世代以降)

第二世代まで、ダメージを受けるターン数は拘束されるターン数より1ターン多い。第三世代から、ダメージを受けるターン数と拘束されるターン数は同じ。

バインド(ポケモンwiki

 

そこそこ条件付をしなければなさそうですが、現在実装されているシステムに付与する要素は「毎ターンダメージを受ける」という点のみです。

 

そして、第1世代の技の中でこのバインド状態にできる技は以下の3つのみです。

  1.  しめつける
  2. まきつく
  3. ほのおのうず

 

ほのおのうずとしめつける

 ここで1点問題が出てきました。同じバインド状態といっても、「まきつく」や「しめつける」と違い、「ほのおのうず」でバインド状態にすると出力されるメッセージが異なるという点です。なので、ここで事前に用意したparamを使用します。

 

バインド(/Classes/StateChange/ScBind.php
<?php
require_once(__DIR__.'/../StateChange.php');
 
// バインド
class ScBind extends StateChange
{
 
    /**
    * 正式名称
    * @var string
    */
    protected $name = 'バインド';
 
    /**
    * 状態変化にかかった際のメッセージ
    * @var string
    */
    protected $sicked_msg = [
        'Standard' => '::pokemonは、しめつけられた',
        'FireSpin' => '::pokemonは、ほのおのうずに閉じ込められた',
    ];
 
    /**
    * ターンチェック時に表示されるメッセージ
    * @var string
    */
    protected $turn_msg = [
        'Standard' => '::pokemonは、しめつけられている',
        'FireSpin' => '::pokemonは、ほのおのうずに巻き込まれている',
    ];
 
    /**
    * ターンチェック時に表示されるメッセージ
    * @var string
    */
    protected $recovery_msg = [
        'Standard' => '::pokemonは、しめつけから開放された',
        'FireSpin' => '::pokemonは、ほのおのうずから抜け出した',
    ];
 
}

 

各メッセージにキーを割り振りました。これでバインド状態の際にパラメーターを差し込んでいれば、それに合ったメッセージを取り出すことができます。

 

バインド状態の判定は「行動後」に行うため、checkAfterScに判定を追加しましょう。

 

チェック格納トレイト(/Traits/Battle/CheckTrait.php
/**
* バインド
*/
if(isset($sc['ScBind'])){
    // 最大HPの1/8ダメージを受ける
    $bind = new ScBind;
    // バインドのターンカウントを進める
    $sicked_pokemon->goScTurn('ScBind');
    if($sc['ScBind']['turn'] <= 0){
        // バインド解除
        $sicked_pokemon->releaseSc('ScBind');
        $this->setMessage($bind->getRecoveryMessage($sicked_pokemon->getPrefixName(), $sc['ScBind']['param']));
    }else{
        // 小数点以下切り捨て
        $damage = (int)($sicked_pokemon->getStats('HP') / 8);
        if($damage){
            // 最小ダメージ数は1
            $damage = 1;
        }
        // ダメージ計算
        $sicked_pokemon->calRemainingHp('sub', $damage);
        // メッセージ
        $this->setMessage($bind->getTurnMessage($sicked_pokemon->getPrefixName(), $sc['ScBind']['param']));
        // ひんし判定
        if($this->checkFainting($sicked_pokemon)){
            return false;
        }
    }
}

 

こちらは毒ダメージの判定や、こんらんの解除チェック判定を組み合わせたような処理になります。メッセージを取得する際には、そのパラメーターを引数として渡してバインド状態に合ったメッセージを受け取ります。

 

今回は「ほのおのうず」を使って確認してみましょう。

 

ほのおのうず(/Classes/Move/FireSpin.php
<?php
require_once(__DIR__.'/../Move.php');
 
// ほのおのうず
class FireSpin extends Move
{
 
    /**
    * 正式名称
    * @var string
    */
    protected $name = 'ほのおのうず';
 
    /**
    * 説明文
    * @var string
    */
    protected $description = '相手をバインド状態にし、2〜5ターン連続でHPを減らし続ける。相手は逃げたり交換したりすることができなくなる。';
 
    /**
    * タイプ
    * @var string
    */
    protected $type = 'Fire';
 
    /**
    * 分類
    * @var string(physical:物理|special:特殊|status:変化)
    */
    protected $species = 'special';
 
    /**
    * 威力
    * @var integer
    */
    protected $power = 35;
 
    /**
    * 命中率
    * @var integer
    */
    protected $accuracy = 85;
 
    /**
    * 使用回数
    * @var integer
    */
    protected $pp = 15;
 
    /**
    * 優先度
    * @var integer
    */
    protected $priority = 0;
 
    /**
    * 追加効果
    *
    * @param array $args
    * @return void
    */
    public function effects(...$args)
    {
        /**
        * @param Pokemon $atk 攻撃ポケモン
        * @param Pokemon $def 防御ポケモン
        */
        list($atk, $def) = $args;
        // 相手をバインド状態にする
        $msg = $def->setSc('ScBind', random_int(4, 5), 'FireSpin');
        // メッセージをセット
        $this->setMessage($msg);
    }

}

 

 

 

  

やどりぎのタネ

 最後は「やどりぎのタネ」状態を実装します。他と違い、ダメージを与え且つ回復するという味方と相手どちらにも処理が必要になる状態変化です。checkAfterScの第2引数はこのために使用します。

毎ターン最大HP1/8(第一世代では1/16)が減り、相手のHPがその分回復する(小数点は切捨て)

やどりぎのタネ_(状態変化)(ポケモンwiki

 

では「やどりぎのタネ」の状態変化クラスを作成しましょう。

 

やどりぎのタネ:状態変化(/Classes/StateChange/ScLeechSeed.php
<?php
require_once(__DIR__.'/../StateChange.php');
 
// やどりぎのタネ
class ScLeechSeed extends StateChange
{
 
    /**
    * 正式名称
    * @var string
    */
    protected $name = 'やどりぎのタネ';
 
    /**
    * 状態変化にかかった際のメッセージ
    * @var string
    */
    protected $sicked_msg = '::pokemonは、やどりぎのタネを植え付けられた';
 
    /**
    * すでにこの状態変化にかかっている際のメッセージ
    * @var string
    */
    protected $sicked_already_msg = '::pokemonは、既にやどりぎのタネを植え付けられている';
 
    /**
    * ターンチェック時に表示されるメッセージ
    * @var string
    */
    protected $turn_msg = 'やどりぎのタネが::pokemonの体力を吸収している';
 
}

 

体力の吸収

 次に「やどりぎのタネ」のチェック処理を作成します。

処理自体は至って簡単です。状態変化にかかっているポケモン($sicked_pokemon)にダメージを与え、相手ポケモン($enemy_pokemon)のHPを回復させます。こちらも行動後(checkAfterSc)に記述します。

 

チェック格納トレイト(/Traits/StateChange/ScLeechSeed.php
/**
* やどりぎのタネ
*/
if(isset($sc['ScLeechSeed'])){
    // 最大HPの1/8HPを吸収する
    $leech_seed = new ScLeechSeed;
    // 小数点以下切り捨て
    $damage = (int)($sicked_pokemon->getStats('HP') / 8);
    if($damage){
        // 最小ダメージ数は1
        $damage = 1;
    }
    // ダメージ計算
    $sicked_pokemon->calRemainingHp('sub', $damage);
    // 回復
    $enemy_pokemon->calRemainingHp('add', $damage);
    // メッセージ
    $this->setMessage($leech_seed->getTurnMessage($sicked_pokemon->getPrefixName()));
    // ひんし判定
    if($this->checkFainting($sicked_pokemon)){
        return false;
    }
}

 

ダメージ判定の後に、回復処理を行なっています。「やどりぎのタネ」を使って出力結果をみてみましょう。

 

やどりぎのタネ:技(Classes/Move/LeechSeed.php
<?php
require_once(__DIR__.'/../Move.php');
 
// やどりぎのタネ
class LeechSeed extends Move
{
 
    /**
    * 正式名称
    * @var string
    */
    protected $name = 'やどりぎのタネ';
 
    /**
    * 説明文
    * @var string
    */
    protected $description = '相手をやどりぎのタネ状態にし、毎ターン相手の最大HPの1/8を奪って、その分自分のHPを回復を回復させる。自分が交代しても効果は続く。';
 
    /**
    * タイプ
    * @var string
    */
    protected $type = 'Grass';
 
    /**
    * 分類
    * @var string(physical:物理|special:特殊|status:変化)
    */
    protected $species = 'status';
 
    /**
    * 威力
    * @var integer
    */
    protected $power = null;
 
    /**
    * 命中率
    * @var integer
    */
    protected $accuracy = 90;
 
    /**
    * 使用回数
    * @var integer
    */
    protected $pp = 10;
 
    /**
    * 優先度
    * @var integer
    */
    protected $priority = 0;
 
    /**
    * 追加効果
    *
    * @param array $args
    * @return void
    */
    public function effects(...$args)
    {
        /**
        * @param Pokemon $atk 攻撃ポケモン
        * @param Pokemon $def 防御ポケモン
        */
        list($atk, $def) = $args;
        // 相手をやどりぎのタネ状態にする
        $msg = $def->setSc('ScLeechSeed');
        $this->setMessage($msg);
    }
 
}

 

 

 

 

 

状態変化はバトル中のみ引き継ぎの必要があるため、敵ポケモン(enemy)と同様にsessionに格納して保管、引き継ぎ処理を追加しておきましょう。

以上で状態変化の処理実装は完了です。

 

まとめ

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

今回のPHPポケモンでは「状態変化」の実装方法をご紹介しました。

ポケモンには様々な状態変化があり、シリーズを経る毎に実装されています。バトルに置いては一つの楽しみ要素であり、さらに戦略的に用いられるものなど数多くあります

ゲームづくりに興味がある人は、ぜひ参考にしてみてくださいね。

 

注目の記事

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

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

【Laravel7】既存makeテンプレートのカスタマイズ Requestサンプル有り
プログラミング
Laravel,Linux,PHP
【Laravel7】既存makeテンプレートのカスタマイズ Requestサンプル有り

  Laravel7では新しい機能が様々導入されており、Webアプリケーションの開発がよりスムーズなものとなってきています。その中でも、もどかしい場所へ手を届いたと感じさせてくれたのが、既存makeコマンドのstubを簡単にカスタマイズできるようになったことです。   今回は既存make用stubの取得コマンドと、リ...

自称デザイナーがおしゃれ名刺を作成してみた!2度見したくなる名刺とは?
デザイン
Adobe,Illustrator
自称デザイナーがおしゃれ名刺を作成してみた!2度見したくなる名刺とは?

  自称デザイナーらしく、オリジナルデザインの名刺を作成しました。 今回作った名刺はコチラです。   会社名や住所、名前の部分は仮で当てはめています。公開情報なのでそのままでも良いんですが一応です。   今回は「自称デザイナーがおしゃれ名刺を作成してみた!2度見したくなる名刺とは?」につい...

【Laravel】1対1リレーションをわかりやすく解説(belongsTo)
プログラミング
Laravel,PHP
【Laravel】1対1リレーションをわかりやすく解説(belongsTo)

Laravelの1対1リレーションのbelongsToについて、公式マニュアルでは専用単語ばかりでどうしてもわかりにくいと感じてしまっている方へ向けて、わかりやすく解説しました。 ※例で紹介しているコードについては、一部英語を日本語表記で使用している部分もありますので、コピペで使用する方は必要に応じて置き換え...

PHPポケモン「バトルシステム編〜状態異常1〜」30
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「バトルシステム編〜状態異常1〜」30

状態異常チェック 今回は少し先延ばししていた状態異常判定を一部作成していきましょう。 状態異常では「行動前」と「行動後」に判定するものに分けることができます。 行動前 まひ、ねむり、こおり  行動後 どく、もうどく、やけど   まずは簡単な行動前から実装していきます。行動前に判...

SEOで強いURLとは?安易に決めると危険だった!「よく分かるSEO対策」パーマリンク編
SEO対策
WordPress,ブログ
SEOで強いURLとは?安易に決めると危険だった!「よく分かるSEO対策」パーマリンク編

  パーマリンクの設定ってSEO対策に関係あるの?   意外と気になっているポイントではないでしょうか。実は、URLとSEO対策には全くの無関係ではなく、安易に決めてしまうとせっかく積み上げた資産的価値を台無しにしてしまうかも知れない危険なポイントでもあるのです。   今回は、ブログの収益化を目指...

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

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

OSI参照モデルとTCP/IP 〜ネットワークモデルとは〜【第3回 ド素人のためのネットワーク講座】
ネットワーク
OSI参照モデル,TCP/IP,ネットワークモデル,プロトコル
OSI参照モデルとTCP/IP 〜ネットワークモデルとは〜【第3回 ド素人のためのネットワーク講座】

  ド素人のためのネットワーク講座! 栄えある第3回は「ネットワークモデル」についてです。   横文字や英字が多くなってきたり、歴史的経緯が関係してきたりとややこしくなってくる部分ですが、ネットワークを理解するためには押さえておきたいポイントです。   プログラミングやシステムエンジニアとし...

カテゴリ

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