プログラミング

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ポケモンは「タイプ実装編」についてご紹介しました。

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

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

 

注目の記事

PHPポケモン「タイプ実装編」15
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「タイプ実装編」15

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

ピカチュウから学ぶオブジェクト指向 〜ステータス導入編〜 6
プログラミング
PHP,PHPポケモン,オブジェクト指向,ポケモン
ピカチュウから学ぶオブジェクト指向 〜ステータス導入編〜 6

  PHPをピカチュウ(ポケモン)から学ぶ大人気コーナー、第6回目は「ステータス機能の導入編」です。   前回(第5回)で終了段階でのサンプルコードを公開しているので、もし本記事から始める人はぜひそちらを参考にしてください。    ※お詫び   調べたところによると、ポケモンの経験...

PHPポケモン「オートローダー編」16
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「オートローダー編」16

  今までは技やタイプを一括requireという荒業で対応していましたが、フシギダネ系列の技を実装した際に「こんなん全部読み込んでられるか!」と流石になったので、簡易ながらオートローダーを実装していきます。 そして、実装したらしたで色々と問題も浮かび上がってきたので、このあたりは回を進めて行きなが...

わざマシン編 忘れさせる技の選択 PHPポケモン106
プログラミング
PHP,PHPポケモン,ポケモン
わざマシン編 忘れさせる技の選択 PHPポケモン106

忘れさせる技の選択 わざマシンによる技習得処理を作成しましたが、既に覚えている技が4つあると、モーダルが表示されて選択をしても習得することができません。これは、技習得用のサービスがホーム画面には用意されていないからです。 なので今回は、わざマシンを使った際の技の入れ替え処理を実装していきましょう...

ブログで生活するための7つの道のり 〜収益化と拡散の方法教えます〜
ライティング
Facebook,Google AdSense,Twitter,ノマドワーク
ブログで生活するための7つの道のり 〜収益化と拡散の方法教えます〜

  ブログで生活したい   毎日数時間、ブログを書くだけで生きていける、そんな夢のような生活を実現させたいと思い描く人は多いですが、簡単なことでは有りません。 ですが、やらなければいけないことがわかっていれば、収益化するのは簡単です。   今回は「ブログで生活するための7つの道のり」をテ...

【Laravel】論理削除対応型existsバリデーションの実装方法
プログラミング
Laravel,PHP
【Laravel】論理削除対応型existsバリデーションの実装方法

  Laravelでは多くのバリデーションが提供されていますが、論理削除を使用している場合はそのままでは使えないものが複数あります。 今回は紐付けをする際に存在チェックで使用するexistsのソフトデリート対応のバリデーションを実装する方法をご紹介します。     カスタムバリデーションの追加   存...

PHPポケモン「レベルアップ進化編」9
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「レベルアップ進化編」9

  PHPポケモン(旧:ピカチュウから学ぶオブジェクト指向)も第9回目となりました。前回GitHubよりコードを配布したので、これから学習しようと考えている人は、ぜひ参考にしてください。   最初からコードの内容について学びたい人は、ぜひ記念すべき第1回から順を追って取り組んでみてください。   ...

ポケモン預かりシステム編 ボックスの作成 PHPポケモン 86
プログラミング
PHP,PHPポケモン,ポケモン
ポケモン預かりシステム編 ボックスの作成 PHPポケモン 86

ポケモン預かりシステムの実装 今回は、前回ざっくりと仕様決めをした「ポケモン預かりシステム」を実装していきます。ボックス内では操作する項目が多いため、ボックス自体に1つの画面を用意して、できる限りPHPによる制御だけで完結できるように作成していきます。   ボックスクラスの作成 それではまず、今...

カテゴリ

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