プログラミング

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

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

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

 

注目の記事

フォームはもう古い?サイトのCVRを高くするチャットシステムとは
マーケティング
CVR,ECショップ
フォームはもう古い?サイトのCVRを高くするチャットシステムとは

  サイトのコンバージョン率を上げたい お問い合わせフォームから連絡が来ない   ちょっとWebサイトやネットショップを立ち上げても中々思うような結果につながらない時代になりました。数多くのサイトが出回っていることはもちろん、ユーザーの閲覧頻度が増えて目が肥えているというのも大きな理由の1...

TwitterでYouTubeのリンク付きサムネイルを表示させる方法【超実践的Webプログラミング活用法】
プログラミング
HTML,JavaScript,PHP,Twitter,YouTube
TwitterでYouTubeのリンク付きサムネイルを表示させる方法【超実践的Webプログラミング活用法】

  Twitter(ツイッター)をブログや商品、イベントの宣伝目的で使用している人は多いです。そして、そのためのマーケティング方法や戦略は数多く練られています。 今回は、その中でもYouTubeの告知をするために特化させた内容をまとめました。   一般的な方法と、プログラミングの知識(HTMLやJavascript等)があ...

ネコにこばん編 PHPポケモン73
プログラミング
PHP,PHPポケモン,ポケモン
ネコにこばん編 PHPポケモン73

ネコにこばんとは 初代ポケモンでは、基本的にトレーナーとのバトルでしかお金を増やすことができず、もし手持ち金が0円の状態で金が必要なイベントが発生すると詰んでしまうという隠された落とし穴がありました。 ですが、初代でも唯一トレーナー意外からお金を得る方法があります。それが「ネコにこばん」という...

なぜ、お金を配るの?悪質メール・SNSを利用した詐欺的手法への対処法とは
ネットワーク
amazon,SNS,Twitter,お金配り,楽天,迷惑メール
なぜ、お金を配るの?悪質メール・SNSを利用した詐欺的手法への対処法とは

定期的に書きたくなるコラムのコーナー! 今回は、迷惑メールやSNSのDMを活用した悪質な勧誘、巷で流行っているお金配りを隠れ蓑のした巧妙な詐欺的手法などをいくつかご紹介、その対策・リクス回避の方法をまとめました。   まず結論からお伝えすると 「怪しいと思うなら手を出すな」 です。その詳細を知りたい...

動画編集で知っておくべき基本的な3工程
動画編集
Adobe,AfterEffects,Illustrator,Photoshop,PremierePro
動画編集で知っておくべき基本的な3工程

  YouTubeに動画を投稿したいけど、動画の基本的な作成手順がわからない・・・   動画作成をするためのソフトは色々ありますが、有料なものであればやはりAdobe製品に軍配が上がります。 しかし準備したは良いものの、いろんなソフトが合ってどれを使えばよいか分からないという悩みを抱えている方は非常...

ゆびをふる編 PHPポケモン 69
プログラミング
PHP,PHPポケモン,ポケモン
ゆびをふる編 PHPポケモン 69

ゆびをふるとは 今回PHPポケモンで実装する技は「ゆびをふる」です。  ゆびをふる(ポケモンwiki) https://wiki.ポケモン.com/wiki/ゆびをふる   「ゆびをふる大会」というゆびをふるのみを使った大会なども開催されているということもあり、ポケモンの技の中でも初代から長く愛されてきた1つです。で...

【jQuery】移動式マルチプルフォームの作り方【sortable】
プログラミング
HTML,JavaScript,jQuery,jQuery UI
【jQuery】移動式マルチプルフォームの作り方【sortable】

  移動式マルチプルフォーム       htmlの標準マルチプルフォームは、選択したものに色が付く仕様ですが、数が多くなってくると選択しているものがわかり難いということや、並び順の変更がしにくいという難点があります。そういった条件も込みで再現するような選択要素移動式の...

HTMLの基本設計「よくわかるSEO対策」構造化(マークアップ)編
SEO対策
HTML,SEO,マークアップ
HTMLの基本設計「よくわかるSEO対策」構造化(マークアップ)編

  HTML5がリリースされて随分経ちました。 それにより多くのタグが増え、それにより今までデザインを目的と使用されていたものが「構造化」という本来の役割を持たされるようになりました。    構造化は、目に見えにくい部分です   それぞれの役割を理解していなければ、せっかくきれいなサ...

カテゴリ

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