プログラミング

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

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

 

大人気?シリーズ「ピカチュウから学ぶオブジェクト指向」、今回はレベルシステムの導入編です。

 

第1回(基礎編)第2回(クラス継承編)で作成したPokemonPikachuのクラスを使用するので、最初から学習したい人はぜひご参考ください。

ピカチュウから学ぶオブジェクト指向 〜入門編〜 1 ピカチュウから学ぶオブジェクト指向 〜入門編〜 1

オブジェクト指向とは  オブジェクト指向プログラミング https://ja.wikipedia.org/wiki/オブジェクト指向プログラミング オブジェクト指向プログラミングとは、互いに密接な関連性を持つデータとメソッドをひとつにまとめてオブジェクトとし、それぞれ異なる性質と役割を持たせたオブジェクトの様々な定...

ピカチュウから学ぶオブジェクト指向 〜クラス継承編〜 2 ピカチュウから学ぶオブジェクト指向 〜クラス継承編〜 2

  ピカチュウから学ぶオブジェクト指向の第2弾はオブジェクトの継承についてです。 前回作成したピカチュウクラスを使用するので、もし基礎的な内容を学習したい人は、以下の記事を参考にしてください。 [shortcode_url_og url="https://s-yqual.com/blog/1035" title="" target="yqual_sub"]   オブジェク...

  

 

レベルシステムの導入

 

ポケモンのゲームと言えば、レベルシステムが楽しみの一つです。RPGゲームでは王道とも言えるレベルという概念は、育てることの楽しみや、強くなることで新しい技や変化が起こるという期待感を与えてくれます。

第3回では第1回、第2回で学んだオブジェクト指向の予習をしながら増設していきます。その上で、レベルという概念の初期準備をしていきましょう。

 

 

保守性を高める

 

第3回となれば、記述量も増えてきました。実際の開発でも役立つよう、本来のシステム開発により近い状態にすること意識して、以下の2点を意識しながら進めていきます。

ファイルの分割

コメントの追加

 

 

ファイルの分割

 

メソッドやプロパティが増えてくれば、それだけ記述量が多くなり、1ファイルの可視性は悪くなります。オブジェクト指向で使用するクラスは、基本的に1クラス1ファイル(クラス名.php)です。なので、今回作成したポケモンとピカチュウのクラスと実行ファイルを以下の階層で分割していきましょう。

/index.php(実行ファイル)
/Class/Pikachu.php(ピカチュウ※子)
/Class/Pokemon.php(ポケモン※親)

 

ファイルを分割すれば、それぞれで必要なファイルを読み込まなければなりません

まずは、ピカチュウクラスのファイル(/Class/Pikachu.php)の最上部に以下の記述を追加します。

require_once('/Class/Pokemon.php');

 

extendsでポケモンのクラスを継承しているため、Pokemon.phpを読み込まなければなりません。それに対してポケモンクラスは読み込まれている継承元のため、現在は特に別ファイルを読み込む必要がありません

 

次に、実行ファイル(/index.php)の最上部に以下の記述を追加します。

require_once('Class/Pikachu.php');

 

実行ファイルではピカチュウのインスタンス(実体)をするためにnew Pikachuと呼び出しています。そのため、実行ファイルではPikachu.phpを読み込まなければなりません。

 

 

コメントの追加

 

ファイル分けをすれば、次にコメントに記述を見直していきます。以下参考URLです。

 

コメントにも書き方があります。特にチーム開発をするのであれば、どういった記法をするのか共有して置かなければなりません

※今回のポケモンに関しては、参考URLの書き方を完全に遵守しているわけではありませんが、比較的同じようにわかりやすくまとめていきます

# ピカチュウクラス内
/**
* 正式名称
* @var string(min:1 max:5)
*/
protected $name = 'ピカチュウ';
 
# ポケモンクラス内
/**
* 正式名称を取得する
* @return string
*/
public function getName()
{
    return $this->name;
}

 

オブジェクト指向を使った開発の場合、多くのメソッドやプロパティを使用するため、それがどういった値を格納しており、引数や返り値などがひと目で分かるようにしておくことが保守性を高めることに繋がります。これはPHPに限らず他の言語についても同様です。

プログラミングに余裕が出てくれば、コメントの記法についても頭に入れておくことをオススメします。

 

 

初期レベルの実装

 

保守性について少し触れたところで、レベルシステムを実装するための開発を進めていきましょう。

ポケモンは捕まえた時(出現したとき)に初期レベルが設定されています。中には決まったレベルのポケモンもいますが、野生の場合は前後1〜2レベルぐらいのことが多いです。

そのためにも、まずは初期レベルの振れ幅をピカチュウのクラスへ追加しましょう。 

 

ピカチュウのクラス(/Class/Pikachu.php)
/**
* 初期レベル
* @var array
*/
protected $default_level = [
    7, 8, 9,
];

 

初期レベルはポケモンによって異なるため、親クラスではなくピカチュウクラスへ設定しています。今回は7〜9レベルの幅で出現させます。 

次に、レベルをセットするためのメソッドをポケモンクラスに追加します。

 

ポケモンのクラス(/Class/Pokemon.php)
/**
* 現在のレベル
* @return integer
*/
protected $level;

 

次に、ポケモンが出現または捕まえた時(インスタンス時)に初期レベルを決定したいので、コンストラクタ(__constract)内に初期レベルを設定するメソッドを記述し、メソッドは全ポケモン共通で使用できるためポケモンクラスに用意します。

 

ポケモンのクラス(/Class/Pokemon.php
<?php
// ポケモン
abstract class Pokemon
{

… 一部省略

    /**
    * レベルをセットする
    * @return void
    */
    protected function setLevel()
    {
        // 初期レベルからランダムで値を取得
        $key = array_rand($this->default_level);
        $this->level = $this->default_level[$key];
    }

}

 

ピカチュウのクラス(/Class/Pikachu.php
<?php
require_once('Class/Pokemon.php');

// ピカチュウ
class Pikachu extends Pokemon
{

… 一部省略
 
    /**
    * インスタンス作成時に実行される処理
    */
    public function __construct()
    {
        $this->setLevel();
        echo 'ピカチュウをゲットした';
    }
 
}

 

コンストラクタ内に記述していたニックネーム設定用のメソッドを削除しました。こちらは後ほど呼び出す形式で実装しましょう。

追加で、呼び出した際にそのことがわかるように、echoを使って「ピカチュウをゲットした」というメッセージを出力しています。

 

では、初期レベルをセットしているポケモンクラス内のsetLevelのメソッドの処理を確認してみましょう。

/**
* レベルをセットする
* @return void
*/
protected function setLevel()
{
    // 初期レベルからランダムで値を取得
    $key = array_rand($this->default_level);
    $this->level = $this->default_level[$key];
}

 

初期レベルを設定するメソッドは、外部から呼び出しをされては困りますので、アクセス修飾子はprotectedになります。

まずは、default_levelに格納されている数値(レベル)をランダムで取得するためにarray_randを使用します。 

 

array_randの返り値はランダムで取得した値が格納されているキーを返却してくれます。なので、$this->default_levelに対して取得したキーを指定して、レベル($this->level)に格納します。

$this->level = $this->default_level[$key];

 

では、index.phpを以下の用に記述して出力結果を確認してみましょう。

 

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

require_once('Class/Pikachu.php');
 
$pikachu1 = new Pikachu;
$pikachu2 = new Pikachu;
?>

<p>ピカチュウ1のレベル:<?=$pikachu1->getLevel()?></p>
<p>ピカチュウ2のレベル:<?=$pikachu2->getLevel()?></p>

 

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

※一部改行して表示させています

# 出力結果
ピカチュウをゲットした
ピカチュウをゲットした
ピカチュウ1のレベル:8
ピカチュウ2のレベル:7

 

それぞれ初期レベルの範囲内で別の値が割り振られていますね。もちろん上記の設定では3通りしかないので、同じレベルのピカチュウがゲットできることもあります。

 

 

レベルに合わせた技の習得

 

レベルが高ければ、それに合わせて技を覚えている場合がありますね。初代(赤・青・緑)のピカチュウであれば、レベルが9になると「でんじは」という技を覚えます。なので、技リストに対して習得レベルを割り当てましょう。

 

ピカチュウのクラス(/Class/Pikachu.php
/**
* レベルアップで覚える技
* @var array
*/
protected $level_move = [
    [1, 'でんきショック'],
    [1, 'なきごえ'],
    [9, 'でんじは'],
    [16, 'でんこうせっか'],
    [26, 'スピードスター'],
    [33, 'こうそくいどう'],
    [43, 'かみなり'],
];

 

ピカチュウのクラスに対して、level_moveというプロパティを追加し、習得レベルと技名称を1行に格納しました。ここまでくればデータベースで管理するのが一般的ですが、今回は簡易のアプリケーションのため、現段階はPHPだけで実装していきます。

注意ポイントは、レベルはkeyとして割り振らず、名称と同様に値(value)として割り振っている点です。初期技や同レベルで習得できる技があると重複するというのが理由です。

 

次に、ピカチュウクラスに設定していたmoveプロパティ(技の一覧)の初期として技を入れる必要が無くなったので、空配列を初期値としてポケモンクラスへ移動しておきましょう。

 

ポケモンのクラス(/Class/Pokemon.php
/**
* 覚えている技
* @var array
*/
protected $move = [];

 

次に、初期技をセットするためのメソッドを作成しましょう。こちらも全ポケモン共通で使用できるのでポケモンのクラスへ追加します。

ポケモンのクラス(/Class/Pokemon.php)
/**
* 技を覚える
* @return string
*/
public function setMove($move)
{
    $this->move[] = $move;
    if(count($this->move) > 4){
        unset($this->move[0]);
    }
}
 
… 一部省略

/**
* 初期技をセットする
* @return void
*/
protected function setDefaultMove()
{
    foreach($this->level_move as list($level, $move)){
        if($level <= $this->level){
            // 現在レベル以下の技であれば習得
            $this->setMove($move);
        }else{
            // 現在レベルを超えていれば処理終了
            break;
        }
    }
}

  

まずは追加したsetDefaultMoveのメソッドから確認していきましょう。

foreach($this->level_move as list($level, $move)){

 

foreachを使用して、レベルで習得する技の一覧($this->level_move)を上から順に回していきます。asの後ろは$valのように値を取得せず、list関数を使用します。

 

foreachで回す際に取得できる値は、レベルと技名称が格納された配列です。それを添え番で取り出すよりも名称のついた変数として取り出せる方が都合が良いので、今回はlistを使用しています。配列の左から順にlist内で指定した変数へ格納されるので、1回目であれば$levelには「1」、$moveには「でんきショック」が格納されています。

 

次にif文を使った条件分岐を使い、格納する技を決めていきます。

if($level <= $this->level){
    // 現在レベル以下の技であれば習得
    $this->setMove($move);
}else{
    // 現在レベルを超えていれば処理終了
    break;
}

 

まず、技レベル($level)と現在のレベル($this->level)を比較します。もし技レベルが現在のレベル以下であれば習得可能なので、技を覚えるためのメソッドであるsetMoveを使用します。

もし、技レベルが現在のレベルより高ければ、その時点で処理を終了します。

※ピカチュウのクラスに設定されているlevel_moveプロパティがレベル順に上から並んでいることを想定しています

 

初期技はレベルと同様にインスタンスを作成した時点で覚えて置かなければなりませんので、ピカチュウクラスのコンストラクタに追記しましょう。

 

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

 

ここのポイントは、メソッドを呼び出す順番です。setDefaultMove(初期技を設定するメソッド)では現在のレベルを使用しています。なので、まずはsetLevel(レベルを設定するメソッド)を記述しておく必要があります。逆になってしまうと技が覚えられなくなってしまうので注意しましょう。

 

それでは、出力ファイル(index.php)に以下を記述して結果を確認してみましょう。

 

出力ファイル(/index.php

※一部改行して表示しています

# 出力結果
ピカチュウをゲットした
ピカチュウをゲットした
 
ピカチュウ1のレベル:9
ピカチュウ1の技
array (
  0 => 'でんきショック',
  1 => 'なきごえ',
  2 => 'でんじは',
)
 
ピカチュウ2のレベル:8
ピカチュウ2の技
array (
  0 => 'でんきショック',
  1 => 'なきごえ',
)

 

レベル9のピカチュウは「でんじは」を覚えており、レベル8のピカチュウは覚えていませんね。これで技に対するレベルの割り振りが完了しました。

 

以下最終コードです。

※第1回、第2回で作成したコードを一部修正しています

 

ポケモンのクラス(/Class/Pokemon.php
<?php
// ポケモン
abstract class Pokemon
{
 
    /**
    * ニックネーム
    * @return string(min:1 max:5)
    */
    protected $nickname;
 
    /**
    * 現在のレベル
    * @var integer
    */
    protected $level;
 
    /**
    * 覚えている技
    * @var array
    */
    protected $move = [];
 
    /**
    * ニックネームを付ける
    * @return string
    */
    public function setNickname($nickname)
    {
        if(empty($nickname) || mb_strlen($nickname, 'UTF-8') > 5){
            echo 'ニックネームは1〜5文字で入力してください';
            return;
        }
        $this->nickname = $nickname;
    }
 
    /**
    * 正式名称を取得する
    * @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;
    }
 
    /**
    * 技を覚える
    * @return string
    */
    public function setMove($move)
    {
        $this->move[] = $move;
        if(count($this->move) > 4){
            unset($this->move[0]);
        }
    }
 
    /**
    * レベルをセットする
    * @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;
            }
        }
    }
 
}

 

ピカチュウのクラス(/Class/Pikachu.php
<?php

require_once('Class/Pokemon.php');

// ピカチュウ
class Pikachu extends Pokemon
{
 
    /**
    * 正式名称
    * @var string(min:1 max:5)
    */
    protected $name = 'ピカチュウ';
 
    /**
    * 初期レベル
    * @var array
    */
    protected $default_level = [
        7, 8, 9,
    ];
   
    /**
    * レベルアップで覚える技
    * @var array
    */
    protected $level_move = [
        [1, 'でんきショック'],
        [1, 'なきごえ'],
        [9, 'でんじは'],
        [16, 'でんこうせっか'],
        [26, 'スピードスター'],
        [33, 'こうそくいどう'],
        [43, 'かみなり'],
    ];
 
    /**
    * インスタンス作成時に実行される処理
    */
    public function __construct()
    {
        $this->setLevel();
        $this->setDefaultMove();
        echo 'ピカチュウをゲットした';
    }
 
}

 

 

まとめ

 

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

今回は「ピカチュウから学ぶオブジェクト指向 〜レベルシステムの導入〜」をご紹介しました。

クラスやメソッド、プロパティの使い方や呼び出し方は、何度も回数をこなせば自然と理解が深まっていきます。興味を持ってくれた人は、ぜひポケモンのゲームにある機能を増設してみたり、他のゲームを参考に練習していくと良いでしょう。

※販売には著作権等の問題を考慮しながら適切な判断をしてください

 

これからPHPを学習しようと考えている方は、ぜひ参考にしてみてくださいね。

 

第4回はコチラ(トレイト編 + 経験値システムの導入)

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

  ピカチュウから学ぶオブジェクト指向の第4弾は「トレイト(trait)の活用」についてです。更に、レベルシステムを導入すれば欠かせない経験値システムも合わせて実装します。 第3回からの続きとなりますので、もし前回をまだ見ていない人は是非ご参考ください。 [shortcode_url_og url="https://s-yqual.c...

 

注目の記事

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

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

PHPポケモン「バトルシステム実装編〜タイプ相性の判定〜」デモ&配布有り 19
プログラミング
jQuery,PHP,PHPポケモン,ポケモン
PHPポケモン「バトルシステム実装編〜タイプ相性の判定〜」デモ&配布有り 19

  システムを組むなら、仕様書や設計書はしっかり作りましょう。   ということで、またまたフォルダ移動やページ分けなどを見えないところでやりました。正直説明すると全く進まなくなりそうなので、改修部分は必要最低限にします。 結論、説明しません。(コード配布するので許してください)   そして今...

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

進化アニメーションの実装 今回は後回しにしていた進化アニメーションの作り込みをしていきます。今までもレベルに達すれば進化はしていましたが、その演出はありませんでした。また、ポケモンではBボタンを押すことで進化のキャンセルをすることができます。なので、この辺りも実際のゲームを再現していきましょう。...

忘れさせる技選択 後編(新しい技を習得) PHPポケモン 56
プログラミング
PHP,PHPポケモン,ポケモン
忘れさせる技選択 後編(新しい技を習得) PHPポケモン 56

新しい技を習得 前編に続き、技習得時の処理分岐を作成していきましょう。今回は「新しい技を習得する」です。 前回は覚えようとしている技を諦めるだけだったので、ポケモンのオブジェクトを書き換える必要がありませんでしたね。ですが、新しく覚えようとしている技を既に覚えている技と置き換える場合は、ポケモ...

PHPポケモン「2進化ポケモン実装編」8
プログラミング
PHP,PHPポケモン,プログラミング学習,ポケモン
PHPポケモン「2進化ポケモン実装編」8

  記念すべき?第8回目で遂にタイトル変更です。 (旧)ピカチュウから学ぶオブジェクト指向 (新) PHPポケモン   機能増設によりオブジェクト指向云々より、PHP学習がメインになったので泣く泣く変更です。(今の所)順調に続いているのも、多くの方?が見てくれているおかげです。感謝感激雨ア...

PHPポケモン「バトルシステム編〜経験値の獲得〜」29
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「バトルシステム編〜経験値の獲得〜」29

経験値の獲得 今まではポケモンに直接経験値を与えるというチートびっくりの仕様でしたが、バトルシステムも終盤に差し掛かってきたので「倒したポケモンから経験値を取得する」というごく当たりまえの仕様を導入していきます。   基礎経験値の設定 では、経験値の計算式に入る前に、必要なパラメーターを1つ用...

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

ゲームバランスの調整 まだまだ開発途中のPHPポケモンはゲームバランスの調整がほとんどされていません。現段階では機能も揃っていない関係上、完全なゲームバランスを求めて行くことにはあまり意味がありませんが、今後調整するための役割として機能自体は作成しておこうというのが今回の目的です。   トレーナ...

PHPポケモン(α)第1回目の大型アプデ
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン(α)第1回目の大型アプデ

第1回目 大型アップデートについて 本日、PHPポケモンの大型アップデートをしました。 今回のアップデートには全体的なデザインチェンジが含まれているため、今まで遊んでくれていた人も、新鮮な気持ちで初められることができるはずです。   デザインについては、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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力