プログラミング

PHPポケモン「タイプ実装編」15

PHP PHPポケモン ポケモン
PHPポケモン「タイプ実装編」15

ポケモンのタイプについて

 2020年剣盾シリーズでのポケモンでは、全18タイプが実装されています。初代では15タイプ(あく、はがね、フェアリーを除く)からスタートして、たった3つのタイプしか増えていない、と感じる方もいるかも知れませんが、この追加に関してもバトルの歴史を大きく動かしてきたのです。また、タイプ相性についても世代を重ねるごとに改変されています。

 

PHPポケモンでは、現在リリースされている18タイプを参考に作成していきます。ポケモンだけではなく、技のタイプについても同様です。

  • ポケモンが覚える技:初代
  • 種族値:最新
  • 技効果:最新
  • タイプ:最新

 

クラスの作成

技やポケモンに比べると情報量は少ないと言えますが、相性などを設定する関係上、タイプに関してもそれぞれクラスを作成し、親となる「タイプ(type)」というクラスを継承させる仕様で進めていきます。

 

子クラス

 まずは子クラスです。手始めにでんき(Electric)を作成しましょう。

 

でんきタイプ(/Classes/Type/Electric.php
<?php
require_once(__DIR__.'/../Type.php');
 
// でんきタイプ
class Electric extends Type
{
 
    /**
    * 正式名称
    * @var string
   */

    protected $name = 'でんき';
 
    /**
    * 攻撃技で使用したときの判定
    */
 
    /**
    * こうかばつぐん
    * @var integer
    */
    protected $excellent = ['Water', 'Flying'];
 
    /**
    * こうかいまひとつ
    * @var integer
    */
    protected $not_very = ['Electric', 'Grass', 'Dragon'];
 
    /**
    * こうかがない
    * @var integer
    */
    protected $doesnt_affect = ['Ground'];
 
}

 ※親クラスは想定で準備しています

 

技の相性判定をするためには、その関係性を持たせて置く必要があります。今回は「実装するタイプクラスで攻撃した場合」の相性をプロパティとして設定しています。

/**
* こうかばつぐん
* @var integer
*/
protected $excellent = ['Water', 'Flying'];

 

例えば、でんきタイプの技は、みず(Water)とひこう(Flying)に相性がよく「こうかばつぐん」です。ダメージの計算上は2倍のダメージ量を与えることができます。もし攻撃した側のexcellentプロパティに受け手側のタイプが含まれているかどうかをチェックすることで判定します。

 

もちろん相性が悪いタイプもあります。その第1段階をnot_varyのプロパティに設定します。

/**
* こうかいまひとつ
* @var integer
*/
protected $not_very = ['Electric', 'Grass', 'Dragon'];

 

でんきタイプの攻撃は、でんき(Electric)とくさ(Grass)とドラゴン(Dragon)の3タイプに相性が悪く、通常の0.5倍のダメージ量しか与えることができません。

 

相性が悪いタイプについては、2段階で構成されており、もう一つをdoesnt_affectのプロパティに設定します。

/**
* こうかがない
* @var integer
*/
protected $doesnt_affect = ['Ground'];

 

でんきタイプの攻撃は、じめん(Ground)には全く効果がありません。0倍のダメージ量です。もし相手のタイプが、みず・じめんの2つを備えていた場合、有利タイプがあったとしてもダメージは与えられません。

 

ポケモンは最大2つのタイプを備えているため、ダメージの判定は以下の6通りから構成されることになります。 

4倍・2倍・1倍・0.5倍・0.25倍・0倍

 

設定例として御三家で使用する「みず・ほのお・くさ・どく」の4タイプ分のサンプルコードを載せておきます。残りの13タイプは相性表を参考に作成してみてください。

ポケモンwiki(第6世代以降を参照)

 

みずタイプ(/Classes/Type/Water.php
<?php
require_once(__DIR__.'/../Type.php');
 
// みずタイプ
class Water extends Type
{
 
    /**
    * 正式名称
    * @var string
    */
    protected $name = 'みず';
 
    /**
    * 攻撃技で使用したときの判定
    */
 
    /**
    * こうかばつぐん
    * @var integer
    */
    protected $excellent = ['Fire', 'Ground', 'Rock'];
 
    /**
    * こうかいまひとつ
    * @var integer
    */
    protected $not_very = ['Water', 'Grass', 'Dragon'];
 
    /**
    * こうかがない
    * @var integer
    */
    protected $doesnt_affect = [];
 
}

 

ほのおタイプ(/Classes/Type/Fire.php
<?php

require_once(__DIR__.'/../Type.php');
 
// ほのおタイプ
class Fire extends Type
{
 
    /**
    * 正式名称
    * @var string
    */
    protected $name = 'ほのお';
 
    /**
    * 攻撃技で使用したときの判定
    */
 
    /**
    * こうかばつぐん
    * @var integer
    */
    protected $excellent = ['Grass', 'Ice', 'Bug', 'Steel'];

    /**
    * こうかいまひとつ
    * @var integer
    */
    protected $not_very = ['Fire', 'Water', 'Rock', 'Dragon'];
 
    /**
    * こうかがない
    * @var integer
    */
    protected $doesnt_affect = [];
 
}

 

くさタイプ(/Classes/Type/Grass.php
<?php

require_once(__DIR__.'/../Type.php');
 
// くさタイプ
class Grass extends Type
{
 
    /**
    * 正式名称
    * @var string
    */
    protected $name = 'くさ';
 
    /**
    * 攻撃技で使用したときの判定
    */
 
    /**
    * こうかばつぐん
    * @var integer
    */
    protected $excellent = ['Water', 'Ground', 'Rock'];
 
    /**
    * こうかいまひとつ
    * @var integer
    */
    protected $not_very = ['Fire', 'Grass', 'Poison', 'Flying', 'Bug', 'Dragon', 'Steel'];
 
    /**
    * こうかがない
    * @var integer
    */
    protected $doesnt_affect = [];
 
}

 

どくタイプ(/Classes/Type/Poison.php
<?php

require_once(__DIR__.'/../Type.php');

// どくタイプ
class Poison extends Type
{
 
    /**
    * 正式名称
    * @var string
    */
    protected $name = 'どく';

    /**
    * 攻撃技で使用したときの判定
    */
 
    /**
    * こうかばつぐん
    * @var integer
    */
    protected $excellent = ['Grass', 'Fairy'];
 
    /**
    * こうかいまひとつ
    * @var integer
    */
    protected $not_very = ['Poison', 'Ground', 'Rock', 'Ghost'];
 
    /**
    * こうかがない
    * @var integer
    */
    protected $doesnt_affect = ['Steel'];
 
}

 

親クラス

 次に親クラスになるType.phpを作成しましょう。

 

タイプ(/Classes/Type.php
<?php
 
// タイプ
abstract class Type
{
 
    /**
    * インスタンス作成時に実行される処理
    *
    * @return void
    */
    public function __construct()
    {
        //
    }
 
    /**
    * タイプ名の取得
    *
    * @return string
    */
    public function getName()
    {
        return $this->name;
    }
 
    /**
    * 攻撃で有利なタイプ
    *
    * @return array
    */
    public function getAtkExcellentTypes()
    {
        return $this->excellent;
    }
 
    /**
    * 攻撃で相性が悪いタイプの取得
    *
    * @return array
    */
    public function getAtkNotVeryTypes()
    {
        return $this->not_very;
    }
 
    /**
    * 攻撃で全く効果が無いタイプの取得
    *
    * @return array
    */
    public function getAtkDoesntAffectTypes()
    {
        return $this->doesnt_affect;
    }

}

 

タイプクラスもインスタンス化する必要がないため、abstractを宣言しています。

今回はgetNameのプロパティしか使用しませんが、残りの関係タイプも取得できるようにしておきましょう。

 

ポケモンへの実装

 それではポケモンにタイプを割り当てしていきましょう。今回もピカチュウを例に実装します。

 

ピカチュウ(/Classes/Pokemon/Pikachu.php
<?php
 
require_once(__DIR__.'/../Pokemon.php');
require_once(__DIR__.'/Raichu.php');
 
// ピカチュウ
class Pikachu extends Pokemon
{
 
    /**
    * 正式名称
    * @var string(min:1 max:5)
    */
    protected $name = 'ピカチュウ';

    /**
    * タイプ
    * @var array
    */
    protected $types = ['Electric'];

 

ピカチュウに対して、typesというプロパティを割り当てました。ピカチュウは1タイプだけですが、フシギダネなど2タイプを持つポケモンもいるため、配列で用意します。

 

次にタイプの取得用メソッド(getTypes)をGetトレイトに作成しましょう。

 

Get格納トレイト(/Traits/Pokemon/GetTrait.php
/**
* タイプの取得
*
* @param string|array|object $return
* @var void
*/
public function getTypes($return='object')
{
    /**
    * タイプ名の取得用関数
    * @param object
    * @var string
    */
    function getTypesName($obj){
        return $obj->getName();
    }
    // array_mapで配列内のタイプクラスをインスタンス化
    $types = array_map([$this, 'getInstance'], $this->types);
    switch ($return) {
        case 'string':
        // array_mapでタイプ名の配列にしたものを、implodeで文字列に変換
        $types = implode(',', array_map('getTypesName', $types));
        break;
        case 'array':
        // array_mapでタイプ名の配列にして返却
        $types = array_map('getTypesName', $types);
        break;
    }
    return $types;
}

 

引数で返却する型を指定できるようにしておきます。タイプはそのまま取得すればクラス名が入った配列です。しかし、出力画面で使用するためには、格納されている各タイプがインスタンス化されているかクラスで設定した名称が取得できなければなりません。状況に合わせて様々な型を受け取れるように、仮でstringarrayobjectの3つを用意しました。

 

それではメソッド内の中腹部分から見てみましょう。

// array_mapで配列内のタイプクラスをインスタンス化
$types = array_map([$this, 'getInstance'], $this->types);

 

まずは、配列に格納されているクラスを全てインスタンス化しなければなりませんので、前回技のインスタンス化をした要領でarray_mapをかけています。コールバック関数を使い回すため、今回はgetInstanceというメソッドを新しいトレイトに作成しました。

 

インスタンス化用トレイト(/Traits/InstanceTrait.php
<?php
trait InstanceTrait
{
    /**
    * インスタンス化関数
    * @param string $class_name
    * @return object
    */
    protected function getInstance($class_name){
        if(class_exists($class_name)){
            return new $class_name();
        }
    }
 
}

 

前回の技取得のコールバック関数で使用したgetMoveInstanceの関数と内容は同じです。こちらのトレイトをポケモンクラスで読み込んでおきましょう

 

Getトレイトの記述に戻ります。次に返り値を引数に合わせて返却するため、switchを使用します。

switch ($return) {
    case 'string':
    // array_mapでタイプ名の配列にしたものを、implodeで文字列に変換
    $types = implode(',', array_map('getTypesName', $types));
    break;
    case 'array':
    // array_mapでタイプ名の配列にして返却
    $types = array_map('getTypesName', $types);
    break;
}
return $types;

 

objectの場合は、そのままを返却するため省略しています。文字列(string)であれば、「くさ,どく」のような形式で返却したいので、インスタンス化したタイプから名前を抽出し、それをimplodeを使って文字列に直します。ここで名前を抽出するために、最初に記述したタイプ名の取得関数を使用します。

/**
* タイプ名の取得用関数
* @param object
* @var string
*/
function getTypesName($obj){
    return $obj->getName();
}

 

受け取ったタイプのオブジェクト(インスタンス)から名前を取得して返却しています。array_mapの返り値は以下のようになっています。

# ピカチュウの場合
['でんき']
 
# フシギダネの場合
['くさ', 'どく']

 

文字列(string)の場合は作成できた配列をimplode、配列希望の場合はそのまま返却しています。

 

それではタイプをポケモンの詳細取得メソッド(getDetails)に追加しましょう。

 

Get格納トレイト(/Traits/Pokemon/GetTrait.php
/**
* 詳細を取得する
* @return integer
*/
public function getDetails()
{
    return [
        '正式名称' => $this->getName(),
        'ニックネーム' => $this->getNickName(),
        'タイプ' => $this->getTypes('string'),
        '現在のレベル' => $this->getLevel(),
        '現在の経験値' => $this->getExp(),
        '次のレベルまで' => $this->getReqLevelUpExp(),
    ];
}

 

出力結果は以下の通りです。

 

 

 

 

技への実装

 

前回実装した技にもタイプが割り振られています。なので、技のタイプ取得用メソッドにも同様の処理を記述します。

 

技クラス(/Classes/Move.php
<?php
require_once(__DIR__.'/../Traits/InstanceTrait.php');
 
// 技
abstract class Move
{
    use InstanceTrait;
 
    /**
    * インスタンス作成時に実行される処理
    *
    * @return void
    */
    public function __construct()
    {
        //
    }
 
--省略
 
    /**
    * タイプの取得
    *
    * @return object
    */
    public function getType()
    {
        return $this->getInstance($this->type);

    }

 

まずは先程作成した、インスタンス化用のトレイトを読み込んでおきます。ポケモンと違い、タイプが配列ではないので、そのままgetInstanceのメソッドにタイプのプロパティ($this->type)をかけてあげるだけでタイプのインスタンスを返すことができます。

 

今回は名前の取得は出力画面側で対応します。

 

出力用ファイル(/index.php
<?php # 覚えている技 ?>
<table class="table table-bordered 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($controller->pokemon->getMove() as $move): ?>
            <tr>
                <th scope="row" class="w-50"><?=$move->getName()?></th>
                <td><?=$move->getType()->getName()?></td>
                <td><?=$move->getPp()?>/<?=$move->getPp()?></td>
            </tr>
        <?php endforeach; ?>
    </tbody>
</table>

 

タイプ用に名称横に1列追加しました。タイプ名の取得は、$move->getType()->getName()のように、メソッドをつなぎ合わせていきながら出力しています。

 

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

 

 

それぞれに割り当てたタイプが出力されていますね。これでタイプシステムの実装が完了です。

  

まとめ

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

今回のPHPポケモンは「タイプ実装編」についてご紹介しました。

技、タイプが揃えば、バトルシステムに必要な要素が整いました。よりポケモンらしくなったとも言えるでしょう。

ゲームやポケモン好きな人プログラミング学習中の方は、ぜひ参考にしてくださいね。

 

注目の記事

アーカイブのディスクリプションを管理画面で設定する方法【SEOに強いWordPressブログ・サイト作り】
プログラミング
PHP,SEO,WordPress
アーカイブのディスクリプションを管理画面で設定する方法【SEOに強いWordPressブログ・サイト作り】

  WordPressで作ったサイトやブログはSEO対策がしやすいという利点があり、より検索に強いサイトへ仕上げることができます。 ですが、SEO対策に特化しているテーマでもアーカイブページのディスクリプション設定ができないものは多く、別で設定する必要があるものがほとんどです。   今回は、より検索で強く...

PHPポケモン「バトルシステム編 〜バトル終了判定〜」28
プログラミング
JavaScript,jQuery,PHP,PHPポケモン,ポケモン
PHPポケモン「バトルシステム編 〜バトル終了判定〜」28

バトル終了判定 今回はバトル終了判定を実装しましょう。今までは「にげる」による戦闘離脱のみで、ひんし状態でも殴り合うことが出来たので、それを解消するためにも戦闘結果による判定を導入します。   ひんし状態の監視 まずは「ひんし」の監視です。現在は交代ポケモンどちらか一方がひんし状態になれば、そ...

くれくれ姿勢が実は起業の近道だった!相手のことを考え過ぎるとハマる落とし穴とは
雑記
フリーランス,独立,起業
くれくれ姿勢が実は起業の近道だった!相手のことを考え過ぎるとハマる落とし穴とは

  仕事ください アドバイスしてください 〇〇について教えてください   こういったくれくれ姿勢の人は多く、投げかけられた側からすると「メリットは?」と感じてしまいます。 ですが実はこのくれくれ姿勢には意外な成功の要因が隠れています。多くの自己啓発記事やツイートをする人はこの本質的なものに触...

熟練者ほど実践するプログラミングが上達する3つの法則
プログラミング
PHP
熟練者ほど実践するプログラミングが上達する3つの法則

  「なかなかプログラミングが上達しない・・・」 「やったことはあるけど覚えられない」   プログラミングを習得しても、勉強と一緒で使っていなければ忘れてしまいます。また、どんどん上達する人や、長い間プログラミングの技術で生計を立てているような熟練者は、日頃からの取り組み方自体が違ってい...

人員配置計算機〜放課後等デイサービス・児童発達支援〜
プログラミング
JavaScript,児童デイ,児童発達支援,放課後等デイサービス,福祉,計算機
人員配置計算機〜放課後等デイサービス・児童発達支援〜

最近はずっとPHPポケモン開発にかかりっきりでしたが、そろそろ「役立つもの」を作りたくなったので、思いつきで作ってみました。 もちろん「汎用性」のあるものは、既に世の中に存在しているため、ありそうでなさそうなニッチなものを攻めてみます。   そんな中、今回挑んだのは「人員配置計算機」です。 ※実際に...

命中率補正と交代技編 PHPポケモン 45
プログラミング
PHP,PHPポケモン,ポケモン
命中率補正と交代技編 PHPポケモン 45

命中率補正とは ダメージ計算や行動順判定には補正(ランク)を計算した結果を反映していましたが、命中率補正についてはまだ未実装だったため、今回はこちらを作成していきたいと思います。 まずはwikiを参考に、計算方法を見ていきましょう。 命中(ポケモンwiki) https:// wiki.ポケモン.com/wiki/命中 第...

フィールド効果技編(しろいきり) PHPポケモン 50
プログラミング
PHP,PHPポケモン,ポケモン
フィールド効果技編(しろいきり) PHPポケモン 50

フィールド効果技とは ポケモンの技の中には、ポケモンに対して状態変化や異常を与えるもの以外に、フィールド自体に効果を持たせるものがいくつかあります。PHPポケモンでは未実装ですが、そういったフィールド効果技はポケモンを交代したとしても場に効果が残り続けます。  場の状態(ポケモンwiki) https:/...

わざマシン編 習得 PHPポケモン105
プログラミング
PHP,PHPポケモン,ポケモン
わざマシン編 習得 PHPポケモン105

わざマシンによる技習得 前回、わざマシンのアイテムクラスを作成したので、今回は実際に使用するまでの処理を作成していきます。 まずは、アイテムクラスに使用時の処理(effectsメソッド)を増設しましょう。   わざマシン01(/Classes/Item/ItemTM01.php) <?php require_once(root_path('Classes').'...

カテゴリ

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