プログラミング

オウムがえし編 PHPポケモン 68

PHP PHPポケモン ポケモン
オウムがえし編 PHPポケモン 68

オウムがえしとは

今回は久々に新しい技を実装します。それが「オウムがえし」です。

オウムがえし(ポケモンwiki

 

初代で登場した技であり、序盤に登場するポッポやオニスズメがレベルアップで覚える技の1つです。最新世代ではオウムがえしという技は実装されなくなった数少ない技の1つでもあります。

それもそのはず、判定がかなり面倒で特別処理が必要な技1つだからです。

※実際の理由は知りません

 

コピーできない技

まず、オウムがえしの技詳細を見てみましょう。

相手が最後に使った技を出す。

 

技名の通り、相手が使った技をそっくりそのまま返してあげる(コピーして使う)のが、この技の仕様となっています。ですが、すべての技をコピーできるわけではありません

 

自分を対象とする技

「せいちょう」や「きあいだめ」など、自身に対してのみ影響を与える技はコピーできません。

自分のフィールドを対象とする技

「しろいきり」や「リフレクター」など、味方フィールドに影響を与える技はコピーできません。

他の技が出る技

「オウムがえし」や「ゆびをふる」など、その技を使うことで別の技が発動する技はコピーできません。

例外

「わるあがき」や「カウンター」はコピーできません。

 

この通り、意外にもコピーできない技は多くあり、それらが相手の最後に使った技と該当する場合は失敗の判定を返す必要があります。

 

ターゲットの設定

まず、大きな括りとして「自分または味方(フィールド)を対象とする技」はコピーできません。なので、技クラスに対して技の対象(target)を設定することで判定ができるようにします。

 

技クラスへのプロパティ追加
/**
* 対象(使ったポケモンから見た立場)
* @var string::friend|enemy
*/
protected $target = 'enemy';

 

この値を取得できるように、親クラスにはgetTargetというメソッドを追加しておきましょう。これで、オウムがえしを発動した際にtargetを確認することで判定することが可能です。

 

では、オウムがえしの技クラスを作成しましょう。

 

オウムがえし(/Classes/Move/MoveMirrorMove.php
<?php
$root_path = __DIR__.'/../..';
require_once($root_path.'/Classes/Move.php');
 
// オウムがえし
class MoveMirrorMove extends Move
{
 
    /**
    * 正式名称
    * @var string
    */
    protected $name = 'オウムがえし';
 
    /**
    * 説明文
    * @var string
    */
    protected $description = '相手が最後に使った技を出す。';
 
    /**
    * タイプ
    * @var string
    */
    protected $type = 'TypeFlying';
 
    /**
    * 分類
    * @var string(physical:物理|special:特殊|status:変化)
    */
    protected $species = 'status';
 
    /**
    * 威力
    * @var integer
    */
    protected $power = null;
 
    /**
    * 命中率
    * @var integer
    */
    protected $accuracy = null;
 
    /**
    * 使用回数
    * @var integer
    */
    protected $pp = 20;
 
    /**
    * 対象(使ったポケモンから見た立場)
    * @var string
    */
    protected $target = 'enemy';
 
    /**
    * オウム返し専用効果
    *
    * @param Pokemon $def 防御ポケモン
    * @param battle_state:object::BattleState バトル状態
    * @return mixed
    */
    public function exMirrorMove($def, $battle_state)
    {
        $black_list = [
            // オウム返し・カウンター・わるあがき・ものまね
            get_class(), 'MoveCounter', 'MoveStruggle', 'Mimic'
        ];
        // 相手が最後に使用した技を取得
        $move_class = $battle_state->getLastMove($def->getPosition());
        // 技が取得できない、またはコピーできない技一覧と一致すれば失敗
        if(
            empty($move_class) ||
            in_array($move_class, $black_list, true)
        ){
            return false;
        }
        // 取得した技をインスタンス化
        $move = new $move_class;
        if($move->getTarget() === 'friend'){
            return false;
        }
        // 成功(技のインスタンスを返却)
        return $move;
    }
 
}

 

オウムがえしでは特別処理が入るため、effectschargeとは違う専用メソッド(exMirrorMove)を作成しました。

まず、先程作成したプロパティ(target)を使って判定できない例外技をブラックリストとして配列を用意します。現在わかる範囲で「オウムがえし」「カウンター」「わるあがき」「ものまね」を用意しました。

※ゆびをふるはターゲット不定のため外しました。ただ、不定を導入する必要がなさそうであれば、自分(friend)の設定にする予定です

 

引数では、判定に必要な相手ポケモンとバトル状態のオブジェクトを取得しています。

まず、バトルオブジェクトから最後に使用した技を取り出します。

※こちらは次項で説明します

もし技使用前(初ターン等)であったり、ブラックリストの技と一致した場合は失敗の判定としてfalseを返却します。その2つをクリアできれば、技をインスタンス化してターゲットを確認、friendであれば失敗とみなしfalseを返却します。

 

技成功の場合は、そのまま取得した技のインスタンスを返り値とします。これで、失敗ならfalse、成功ならコピーできた技を攻撃トレイトへ伝えることができます。

 

バトルシステムへの実装

それでは、バトルで使えるようにするため、バトルシステム内にオウムがえしの判定処理を実装していきましょう。

  

最後に使用した技

まず、前項で登場したバトルシステムから最後に使用した技を取得するための処理を追加します。

 

バトル状態クラス(/Classes/BattleState.php
<?php
/**
* バトル状態クラス
*/
class BattleState
{
 
--省略
 
    /**
    * 最後に使用した技
    * @var array
    */
    private $last_moves;
 
    /**
    * @return void
    */
    public function __construct()
    {
        $this->init();
    }
 
    /**==================================================================
    * 初期化・初期値
    ==================================================================**/
 
    /**
    * 初期化
    * @return void
    */
    public function init() :void
    {
        $this->run = 0;
        $this->dafaultFields();
        $this->dafaultTurnDamages();
        $this->dafaultLastMoves();
    }
 
--省略
 
    /**
    * 最後に使用した技の初期値
    * @return void
    */
    public function dafaultLastMoves() :void
    {
        $this->last_moves = [
            'friend' => '',
            'enemy' => '',
            'all' => '',
        ];
    }
 
--省略
 
    /**==================================================================
    * 最後に使用した技
    ==================================================================**/
 
    /**
    * 最後に使用した技(クラス)の取得
    * @param position:string::friend|enemy|all
    * @return string
    */
    public function getLastMove(string $position = 'all')
    {
        return $this->last_moves[$position];
    }
 
    /**
    * 最後に使用した技(クラス)の格納
    * @param move:object|string::Move
    * @param position:string::friend|enemy
    * @return void
    */
    public function setLastMove(string $position, $move)
    {
        // オブジェクト・文字列(クラス名)両方を許可
        if(is_object($move)){
            $class = get_class($move);
        }else{
            $class = $move;
        }
        $this->last_moves[$position] = $class;
        $this->last_moves['all'] = $class;
    }
 
}

 

他のステータスと同じように、初期値を用意してセット、取得と格納用のメソッドを用意しました。1点異なる点は「すべての最終技」としてallの値をセットできるという点です。こちらは使うかどうかわかりませんが、技や状況によっては必要になる可能性を考慮して実装しておきました。

 

次に、最後に使用した技を格納するタイミングについてです。

ゲームの仕様を確認できていませんが、PHPポケモンでは「発動した技」を最後に使用した技とみなして格納する仕様にしました。

 

例えば以下のような流れが発生したケースで考えてみてください。

「敵:たいあたり」

→「味方:オウムがえし(たいあたり)」

→「敵:オウムがえし(???)」

 

上記の場合、敵が使用した「オウムがえし」ではどの技を返すのが正解なのかです。実際に試してみるとわかるかも知れませんが、技をそのまま格納すると「オウムがえし」が選ばれることになり失敗となります。ですが、実際に発動した技を考慮すれば「たいあたり」をコピーしなければなりません。

PHPポケモンでは「たいあたり」を返せるように、attackメソッドの返り値として技オブジェクトを返却し、attackメソッド直後に最後に使用した技を格納しました。

 

バトルサービス(/App/Services/Battle/FightService.php
/**
* 行動順に攻撃処理
*
* @return boolean (false: ひんしポケモン有り)
*/
private function actionAttack($orders)
{
    foreach($orders as list($atk, $def, $move)){
        // 攻撃ポケモンの怒り解除
        $atk->releaseSc('ScRage');
        // 攻撃(返り値に使用した技を受け取る)
        $attack_move = $this->attack($atk, $def, $move);
        // 最後に使用した技を格納
        $this->battle_state
        ->setLastMove($atk->getPosition(), $attack_move);
        // バトル終了のレスポンスチェック(交代技など)
        if(getResponse('end')){
            break;
        }
        // ひんしチェック
        $this->fainting = [
            $atk->getPosition() => $this->checkFainting($atk),
            $def->getPosition() => $this->checkFainting($def),
        ];
        // どちらかがひんし状態なら処理終了
        if($this->fainting['friend'] || $this->fainting['enemy']){
            $result = false;
            break;
        }
    } # endforeach
    // 結果返却
    return $result ?? true;
}

 

attackメソッドのreturnのタイミングでは、すべて技オブジェクトを返却しています。これで、最終技をバトル状態クラスに格納しています。

 

オウムがえしの特別処理

それでは、attackメソッド内でオウムがえしの判定を追加していきましょう。

 

攻撃トレイト(/App/Traits/Service/Battle/ServiceBattleAttackTrait.php
/**
* 攻撃
* (攻撃→ダメージ計算→ひんし判定)
*
* @param atk_pokemon:object::Pokemon
* @param def_pokemon:object::Pokemon
* @param move:object::Move
* @return object::Move
*/
protected function attack(object $atk_pokemon, object $def_pokemon, object $move) :object
{
    // 補正値の初期化
    $this->m = 1;
    // 行動チェック(状態異常・状態変化)
    if(
        !$this->checkBeforeSa($atk_pokemon) ||
        !$this->checkBeforeSc($atk_pokemon)
    ){
        // 行動失敗
        return $move;
    }
    // 「わるあがき」の確認とPP消費処理
    if(!$this->checkEnabledMove($move, $atk_pokemon)){
        setMessage($atk_pokemon->getPrefixName().'は出すことのできる技がない');
    }
    // 「オウムがえし」の特別処理
    if(get_class($move) === 'MoveMirrorMove'){
        $mirror_move = $this->attackMirrorMove($atk_pokemon, $def_pokemon, $move);
        if(!$mirror_move){
            // 技失敗
            setMessage('しかし上手く決まらなかった');
            return $move;
        }else{
            // ミラー技をセット
            $move = $mirror_move;
        }
    }
    // チャージチェック
    $charge = $move->charge($atk_pokemon);
    if($charge){
        // チャージターンなら行動終了
        setMessage($charge);
        return $move;
    }
 
--省略

 

チャージチェック前にオウムがえしの特別処理を行いました。処理内容が多いのでメソッド分けをしています。

attackMirrorMoveの中身は以下の通りです。

/**
* オウムがえしの特別処理
*
* @param atk:object::Pokemon
* @param def:object::Pokemon
* @param move:object::Move
* @return mixed::Move|false
*/
private function attackMirrorMove($atk, $def, $move)
{
    // オウムがえしで「チャージ状態」になっているかどうかを確認
    $charge = $atk->getChargeMove();
    if($charge){
        return new $charge;
    }
    // オウムがえしで「あばれる状態」になっているかどうかを確認
    $thrash = $atk->getThrashMove();
    if($thrash){
        return new $thrash;
    }
    // オウム返しの発動メッセージ
    setMessage($atk->getPrefixName().'は'.$move->getName().'を使った!');
    return $move->exMirrorMove($def, $this->battle_state);
}

 

ここで注目すべきポイントは「チャージ状態」と「あばれる状態」についてです。この2つの状態ではループが発生するため、状態変化にかかっていれば選択された技がそのまま実行されます。ただオウムがえしの判定をするだけでは「あばれる」をコピーした際に2回目の実行では「あばれる」が選択されず、永久に解除されないという状態に陥ってしまいます。チャージ技をコピーした場合も同じです。

それを回避するためにも2つ状態であれば、オウムがえしの特別処理ではなく「あばれる状態の技」または「チャージ状態の技」を抽出して返却します。

この2つの状態に当てはまらなければ、オウムがえしの処理を発生させ、コピーできた技を返却します。

 

では、実際にオウムがえしを使ってみましょう。

 

通常技に対する「オウムがえし」 

 

「あばれる」に対する「オウムがえし」

 ※「あばれる」は検証用に威力を20にしています。また、ライチュウも検証用として「あばれる」しか使いません

 

それぞれ正常に処理が返りました。これで「オウムがえし」の実装は完了です。

 

まとめ

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

今回のPHPポケモンでは「オウムがえしの実装方法」をご紹介しました。

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

 

注目の記事

ブログ運営者のための「よくわかるSEO対策」フィード編
SEO対策
atom,feedly,rss,WebSub,WordPress,xml,フィード
ブログ運営者のための「よくわかるSEO対策」フィード編

  アメブロやFC2など優れたブログサービスが存在している中、好きなデザイン、こだわった機能を求めてWordPressを選択される方も多いですね。 また、コーポレートサイトにWordPressを用いる方もいるでしょう。ただしSEO対策がしっかりとされていなければ、提供されているサービスに太刀打ちできません。  もちろん...

ポケモンセンター編 PHPポケモン 37
プログラミング
PHP,PHPポケモン,ポケモン
ポケモンセンター編 PHPポケモン 37

ポケモンセンター  バトルシステムを作る関係上、どうしてもダメージを受けることが多くなってきたので、そろそろポケモンセンターを建設(作成)します。 とは言っても、ポケモンセンターに行って交換やらボックス整理などができるわけではなく、ただ回復ポイントを設置するだけの簡単な処理です。   HPの回復 ...

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

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

デザイン
サムネイル,デザイナー,バナー,広告
デザイナーにセンスは必要ない!誰でも作れるおしゃれなサムネイル

  「デザイナーになるためにはセンスが必要ですか?」   バナーづくりの小規模講習会を実施した際に、この質問した人がいました。 よくある質問なのですが、いつも決まって自分の回答は「NO」です。   実際に一流のデザイナーとして活躍するレベルまでいくには、確かにセンスと呼ばれているものが必要...

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

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

人に相談しても期待はするな【行動もどきって?成功する人と失敗する人の違いとは】
雑記
自己啓発
人に相談しても期待はするな【行動もどきって?成功する人と失敗する人の違いとは】

  「とにかく行動しろ」 「いろんな人に会え」 「どんどん外注しろ」   どれも覚えておきたい教訓ではありますが、その本質が見抜けなければ逆効果になります。 行動であっても、それが行動もどきになっている人は多く、人に会って人生が変わるということも受け身であれば全く意味がありません。外注に...

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

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

壁技編(リフレクター・ひかりのかべ)PHPポケモン 51
プログラミング
PHP,PHPポケモン,ポケモン
壁技編(リフレクター・ひかりのかべ)PHPポケモン 51

壁技とは 前回実装した「しろいきり」と同じく、初代から実装されたフィールド効果技が存在します。それが「壁技」です。 壁(ポケモン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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力