プログラミング

ピカチュウから学ぶオブジェクト指向 〜トレイト編〜 4

PHP PHPポケモン オブジェクト指向 ポケモン
ピカチュウから学ぶオブジェクト指向 〜トレイト編〜 4

 

ピカチュウから学ぶオブジェクト指向の第4弾は「トレイト(trait)の活用」についてです。更に、レベルシステムを導入すれば欠かせない経験値システムも合わせて実装します。

第3回からの続きとなりますので、もし前回をまだ見ていない人は是非ご参考ください。

ピカチュウから学ぶオブジェクト指向 〜レベルシステム導入編〜 3 ピカチュウから学ぶオブジェクト指向 〜レベルシステム導入編〜 3

  大人気?シリーズ「ピカチュウから学ぶオブジェクト指向」、今回はレベルシステムの導入編です。   第1回(基礎編)、第2回(クラス継承編)で作成したPokemonとPikachuのクラスを使用するので、最初から学習したい人はぜひご参考ください。 [shortcode_url_og url="https://s-yqual.com/blog/1035"...

 

それでは今回もピカチュウと一緒に、楽しくプログラミング、オブジェクト指向を学習しましょう。

 

 

トレイト(trait)とは

 

 

トレイトは、PHP のような単一継承言語でコードを再利用するための仕組みのひとつです。 トレイトは、単一継承の制約を減らすために作られたもので、 いくつかのメソッド群を異なるクラス階層にある独立したクラスで再利用できるようにします。 トレイトとクラスを組み合わせた構文は複雑さを軽減させてくれ、 多重継承や Mixin に関連するありがちな問題を回避することもできます。

 

トレイトはクラスと似ていますが、トレイトは単にいくつかの機能をまとめるためだけのものです。 トレイト自身のインスタンスを作成することはできません。 昔ながらの継承に機能を加えて、振る舞いを水平方向で構成できるようになります。 つまり、継承しなくてもクラスのメンバーに追加できるようになります。

 

 

だそうです。簡単にまとめるなら

継承しなくても使えるよ!インスタンスも作れないよ!なクラス

 といったところでしょう。

汎用性のあるメソッドをまとめておくイメージです。今回作っているようなポケモンのクラスでも使え、アイテムというクラスでも使えるようなメソッドも場合によっては必要になります。そういったものを毎回書かなくても良いようにまとめて置くのがトレイトの本来の使い方です。

 

 

トレイトの活用

 

前回(第3回)でファイルを分割しましたが、それでも記述量は多くなってきました。特にポケモンクラス内のメソッドが回数を重ねるごとに増えていきます。そこで、今回はトレイト(trait)を使って管理をします。

 

現在ポケモンクラス内にあるメソッドでは「get〜」という取得用のメソッドと、「set〜」という値を格納するようのメソッドで構成されています。なので、get関係set関係をそれぞれまとめて置くように「SetTrait」と「GetTrait」を作成しましょう。作成箇所は以下の通りです。

/Trait/GetTrait.php
/Trait/SetTrait.php

 

それではそれぞれのファイル内を見ていきましょう。

 

Get関係の格納トレイト(/Trait/GetTrait.php
<?php
trait GetTrait
{
 
    /**
    * 正式名称を取得する
    * @return string
    */
    public function getName()
    {
        return $this->name;
    }
 
    /**
    * ニックネームを取得する
    * @return string
    */
    public function getNickname()
    {
        if(empty($this->nickname)){
            return $this->name;
        }
        return $this->nickname;
    }
 
    /**
    * 覚えている技の一覧を取得する
    * @return array
    */
    public function getMove()
    {
        return $this->move;
    }
 
    /**
    * 現在のレベルを取得する
    * @return integer
    */
    public function getLevel()
    {
        return $this->level;
    }
 
}

 

Set関係の格納トレイト(/Trait/SetTrait.php
<?php
trait SetTrait
{
    /**
    * ニックネームを付ける
    * @return string
    */
    public function setNickname($nickname)
    {
        if(empty($nickname) || mb_strlen($nickname, 'UTF-8') > 5){
            echo 'ニックネームは1〜5文字で入力してください';
            return;
        }
        $this->nickname = $nickname;
    }
 
    /**
    * レベルをセットする
    * @return void
    */
    protected function setLevel()
    {
        // 初期レベルからランダムで値を取得
        $key = array_rand($this->default_level);
        $this->level = $this->default_level[$key];
    }
 
    /**
    * 初期技をセットする
    * @return void
    */
    protected function setDefaultMove()
    {
        foreach($this->level_move as list($level, $move)){
            if($level <= $this->level){
                // 現在レベル以下の技であれば習得
                $this->setMove($move);
            }else{
                // 現在レベルを超えていれば処理終了
                break;
            }
        }
    }
 
    /**
    * 技を覚える
    * @return string
    */
    public function setMove($move)
    {
        $this->move[] = $move;
        if(count($this->move) > 4){
            unset($this->move[0]);
        }
    }
 
}

 

それぞれgetsetのメソッドを移動してきました。それではトレイトの宣言部分について確認しましょう。

trait GetTrait

 

クラスとの大きな違いは最初の行にあります。クラスの場合はclassと宣言してからクラス名をつけますが、トレイトの場合はtraitと宣言してトレイト名をつけます。その他の記述方法はほとんど同じですが、宣言が違うということを覚えておきましょう。そして最初の説明でも述べたように、トレイトはインスタンス化(実体化)することができません

 

 

トレイトの読み込み

 

次に、クラスに対してトレイトを読み込む方法を見ていきましょう。今回はどちらもポケモンクラス内で使用していたメソッドなので、ポケモンクラス上で作成した2つのトレイトを読み込みます。

 

ポケモンのクラス(/Class/Pokemon.php
<?php
 
require_once('Trait/SetTrait.php');
require_once('Trait/GetTrait.php');
 
// ポケモン
abstract class Pokemon
{
    use SetTrait;
    use GetTrait;
 
    /**
    * ニックネーム
    * @return string(min:1 max:5)
    */
    protected $nickname;
 
    /**
    * 現在のレベル
    * @var integer(min:2 max:100)
    */
    protected $level;
 
    /**
    * 覚えている技
    * @var array
    */
    protected $move = [];
 
}

 

require_onceで使用するトレイトファイルを読み込みクラス内でトレイトの使用を宣言しています。

use SetTrait;
use GetTrait;

 

注意点は、useをクラス内で使用するということです。現在はまだ紹介していませんが、名前空間やオートローダーを使用するとクラスの前にuseをつけて必要ファイルを読み込みます。それに対して、トレイトの使用宣言はクラス内で行います。

 

これでポケモンのクラスで各トレイトに割り当てたメソッドが使用できるようになりました。ポケモンのクラスで使用できるということは、それを継承しているピカチュウのクラスでも呼び出すことができます。出力用ファイル(index.php)に記述して確認してみましょう。

 

出力用ファイル(index.php
<?php

require_once('Class/Pikachu.php');

$pikachu = new Pikachu;
$pikachu->setNickname('ピカイチ');

?>

<p>ニックネーム:<?=$pikachu->getNickname()?></p>

 

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

# 出力結果
 
ピカチュウをゲットした
 
ニックネーム:ピカイチ

 

 

経験値システムの導入

 

レベルシステムにとって欠かせないのが経験値システムです。その初期準備として、初期経験値の計算と次のレベルアップに必要な経験値の算出を実装します。

そのために、まずポケモンの経験値の仕組みを見てみましょう。 

 

今回はリンク先の「経験レベルと必要経験値の換算表」という部分を参考にします。ポケモンによって異なるようですが、今回は最も単純なピカチュウの経験値タイプでもある「100万型」を実装します。

 

100万型経験値の計算方法は以下の通りです。

必要経験値 = Lv^3

 

もう少しわかりやすく表現すると

必要経験値 = レベル x レベル x レベル

 

上記の式が成り立ちます。PHP(5.6以降)であれば**演算子が使えるので、今回作成しているポケモンシステムであれば、以下の式で現在のレベルに必要な経験値を算出します。

$this->level ** 3

 

 

デフォルト経験値

 

ポケモンは捕まえた時点で、そのレベルに応じた経験値を所有していなければなりません。そのために、経験値を格納しておくプロパティ、デフォルト経験値の算出用メソッド、現在の経験値を取得するメソッドの3つを用意します。

 

  1. 経験値を格納するプロパティ
    ポケモンのクラス(/Class/Pokemon.php)
  2. デフォルトの経験値を算出するメソッド
    Set格納トレイト(/Trait/SetTrait.php) 
  3. 現在の経験値を取得するメソッド
    Get格納トレイト(/Trait/GetTrait.php)

 

ポケモンのクラス(/Class/Pokemon.php
/**
* 経験値
* @var integer
*/
protected $ex_point;

 

Set格納トレイト(/Trait/SetTrait.php
/**
* 初期経験値をセットする
* @return void
*/
protected function setDefaultExPoint()
{
    $this->ex_point = $this->level ** 3;
}

 

Get格納トレイト(/Trait/GetTrait.php
/**
* 現在の経験値を取得する
* @return integer
*/
public function getExPoint()
{
    return $this->ex_point;
}

 

setDefaultExPointのメソッドは、ポケモンを捕まえた時点で実行される必要がありますので、ピカチュウのクラスのコンストラクタで実行しましょう。

 

ピカチュウのクラス(/Class/Pikachu.php
/**
* インスタンス作成時に実行される処理
*/
public function __construct()
{
    $this->setLevel();
    $this->setDefaultExPoint();
    $this->setDefaultMove();
    echo 'ピカチュウをゲットした';
}

 

setDefaultExPoint内でレベルのプロパティ($this->level)が使用されています。なので実行するタイミングはsetLevelのあとでなければなりません

 

では、ピカチュウのインスタンスを作成して、経験値を実行ファイルで確認してみましょう。

 

実行ファイル(/index.php
# 出力結果(1回目)
 
ピカチュウをゲットした
 
現在のレベル:8
現在の経験値:512
# 出力結果(2回目)
 
ピカチュウをゲットした
 
現在のレベル:9
現在の経験値:729

 

換算表で確認してみると、レベル8では512レベル9では729となっているため正常に算出出来ていることがわかります。 

 

これで、初期経験値の設定は完了です。

 

 

次のレベルまで

 

ポケモンの経験値で気になるのは、現在の値よりも次のレベルまでに必要な値です。なので、次のレベルまでの値を算出するメソッドをGet格納トレイトに追加します。

 

Get格納トレイト(/Trait/GetTrait.php
/**
* 次のレベルに必要な経験値
* @return integer
*/
public function getReqLevelUpExPoint()
{
    return ($this->level + 1) ** 3 - $this->ex_point;
}

 

次のレベルまでに必要な経験値の算出方法は以下の通りです。

次のレベルまでに必要な経験値

= 次のレベルで必要な経験値 現在の経験値

 

現在の経験値は$this->ex_pointに格納されています。次のレベルで必要な経験値は以下の式で算出できます。

次のレベルで必要な経験値

= (現在のレベル + 1)の3乗

 

1列にまとめているので複雑な式に見えてしまうかも知れませんが、やっていることは至って単純です。算出式が、以下の通りです。

($this->level + 1) ** 3 - $this->ex_point

 

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

 

実行ファイル(/index.php
<?php

require_once('Class/Pikachu.php');

$pikachu = new Pikachu;

?>

<p>現在のレベル:<?=$pikachu->getLevel()?></p>
<p>現在の経験値:<?=$pikachu->getExPoint()?></p>
<p>次のレベルまでに必要な経験値:<?=$pikachu->getReqLevelUpExPoint()?></p>
# 出力結果
 
ピカチュウをゲットした
 
現在のレベル:7
現在の経験値:343
次のレベルまでに必要な経験値:169

 

現在の経験値(343)と次のレベルまでに必要な経験値(169)を足すと、レベル8で必要な経験値(512)になるので正常に出力されていることがわかります。

 

これで、次のレベルまでに必要な経験値の出力設定が完了です。

 

 

詳細の取得

 

機能が増えてくれば、一つずつ出力するのは一苦労です。なので、一気に詳細を出力できるようなメソッドを作成します。Get格納トレイトに以下を追加しましょう。

 

Get格納トレイト(/Trait/GetTrait.php
/**
* 詳細を取得する
* @return integer
*/
public function getDetails()
{
    return [
        '正式名称' => $this->getName(),
        'ニックネーム' => $this->getNickName(),
        '現在のレベル' => $this->getLevel(),
        '覚えている技' => implode(',', $this->getMove()),
        '現在の経験値' => $this->getExPoint(),
        'レベルアップに必要な経験値' => $this->getReqLevelUpExPoint(),
    ];
}

 ※配列キーに日本語が用いられることはほとんど有りませんが、今回はわかりやすさ重視のために日本語を使用しています。気になる人は値として格納してlistで取得するなどしてください

 

それでは返り値として準備された配列を見てみましょう。

return [
    '正式名称' => $this->getName(),
    'ニックネーム' => $this->getNickName(),
    '現在のレベル' => $this->getLevel(),
    '覚えている技' => implode(',', $this->getMove()),
    '現在の経験値' => $this->getExPoint(),
    'レベルアップに必要な経験値' => $this->getReqLevelUpExPoint(),
];

 

返却する内容は至って単純です。それぞれの取得用メソッドに見出しとなるキーを割り振っています。「覚えている技」は返り値が配列のため、そのまま文字列として出力できるようにimplodeを使用しています。 

 

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

 

実行ファイル(/index.php
<?php

require_once('Class/Pikachu.php');
 
$pikachu = new Pikachu;
$pikachu->setNickname('ピカイチ');
$details = $pikachu->getDetails();

?>
 
<?php foreach($details as $key => $val): ?>
<p><?=$key?>:<?=$val?></p>
<?php endforeach; ?>

 

ピカチュウをインスタンス化(実体化)させて、「ピカイチ」というニックネームをつけました。

詳細の取得メソッド(getDetails)は配列で返ってくるため、$detailsという変数に格納してforeachで見出し($key)と一緒に取り出しています。

 

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

# 出力結果
 
ピカチュウをゲットした
 
正式名称:ピカチュウ
ニックネーム:ピカイチ
現在のレベル:8
覚えている技:でんきショック,なきごえ
現在の経験値:512
レベルアップに必要な経験値:217

 

正常に取得できていますね。

一括取得のメソッドがあれば、すぐにインスタンスの中身が確認ができるため便利です。

 

 

まとめ

 

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

今回は「【PHP】ピカチュウから学ぶオブジェクト指向 〜トレイト編 & 経験値システム導入〜」をご紹介しました。

 

トレイト(trait)の使い方はプロジェクトによっても様々ですが、今回紹介したようにファイル内のメソッドを分割して管理するために用いることも可能です。継承する必要が無いため、複数のクラスで使いまわしするメソッド格納用として使えれば、より保守性も高まり管理手間が少なくなります。

※今回はあくまでトレイトの使い方の説明用として用いているので、それぞれのプロジェクトに合わせた使い方をしてください

 

PHPを学習中の方や、ポケモンやゲームづくりに興味がある人は、ぜひ参考にしてみてくださいね。

 

注目の記事

進化アニメーション 後編 PHPポケモン 60
プログラミング
PHP,PHPポケモン,ポケモン
進化アニメーション 後編 PHPポケモン 60

ポケモンの進化演出 前回に続いて、ポケモンの進化演出を実装していきます。バックエンドの処理はざっと説明をしたので、今回はフロントエンド(JavaScript)側の処理を作成していきましょう。   進化画面は新しく設けたので、こちらにもバトル画面で使っているメッセージ用JSを作成していきます。処理自体はほとん...

XserverにSequel ProでSSH接続する方法を4ステップでわかりやすく解説
ネットワーク
phpMyAdmin,Sequel Pro,SSH,Xserver,データベース,公開鍵,秘密鍵
XserverにSequel ProでSSH接続する方法を4ステップでわかりやすく解説

  AWSなどが注目される中、Xserver(エックスサーバー)は操作やセットアップが簡単で、ポートフォリオや業務、個人ブログ(WordPess)で使用している方に需要が高いサービスです。 そしてMacのPCを使っている方はデータベースの管理ツールとして、無料で使えるSequel Proが人気があり、多くのユーザーが使用し...

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

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

npm run watch-poll中にPCがフリーズした時の解決法
プログラミング
CSS,JavaScript,Laravel,Linux
npm run watch-poll中にPCがフリーズした時の解決法

  Laravelで開発中にPCが頻繁にフリーズするという問題にぶち辺り、原因がnpm run watch-pollだということが解ったので、その解決方法をまとめておきます。 複雑な原因でもなく大きな問題にもならなかったのですが、これが原因でデータ破損となれば困るので、同じような問題に直面した開発者向けです。    ...

【Adobe Animate CC】モーショントゥイーンを使ったアニメーション作成
動画編集
Adobe,Animate,Illustrator,Photoshop,アニメーション
【Adobe Animate CC】モーショントゥイーンを使ったアニメーション作成

    今回はキャラクターがうちわを扇いでいるアニメーションのAdobe Animateを使った作成方法をご紹介します。 完成イメージは以下の通りです。   Photoshopなどを使ってもgifアニメーションの作成はできますが、Adobe Animateのモーショントゥイーンを使えば、変化するポイントだけを設定す...

ポケモン図鑑編 PHPポケモン 88
プログラミング
PHP,PHPポケモン,ポケモン
ポケモン図鑑編 PHPポケモン 88

ポケモン図鑑とは ポケモンに出会ったり、仲間にしたりすると、ポケモン図鑑のデータがどんどんと埋まっていきます。PHPポケモンでもこの仕組みを実現させるために、ポケモン図鑑を作成していきましょう。   クラスによる管理 ポケモン図鑑はクラス管理をしていきます。プレイヤー1人に対して1つのポケモン図...

かなしばり編 PHPポケモン 95
プログラミング
PHP,PHPポケモン,ポケモン
かなしばり編 PHPポケモン 95

かなしばりとは 最近は技のアップデートをおろそかにしていたので、久々の追加実装です。へんしんという再現が面倒な技は乗り越えましたが、他の技も仕様がややこしいため、覚えるポケモンが用意できたタイミングに基本的に増やしていきたいのですが、バトルシステムを作り上げていく関係上、どうしても見逃せない部...

ゲームバランス調整編 DateTimeクラスの活用 PHPポケモン 101
プログラミング
PHP,PHPポケモン,ポケモン
ゲームバランス調整編 DateTimeクラスの活用 PHPポケモン 101

ゲームバランスの調整 まだまだ開発途中の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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力