記念すべき?第8回目で遂にタイトル変更です。
(旧)ピカチュウから学ぶオブジェクト指向
(新) PHPポケモン
機能増設によりオブジェクト指向云々より、PHP学習がメインになったので泣く泣く変更です。(今の所)順調に続いているのも、多くの方?が見てくれているおかげです。感謝感激雨アレレということで、感謝の気持を込めて最後にはGitHubさんよりサンプルコードを配布しているので、ぜひ最後まで読んでからダウンロードしてやってください。
コードの説明については、第1回からできるだけわかりやすく説明をしているので、今回始めての人はぜひご参考ください。
今回は「2進化ポケモン実装編」です。今までピカチュウだけに頼っていましたが、新たに3匹増えるということもあって、ディレクトリ構造を大幅に変更しています。読み込み方法も少し変更したので、以下参考にしながら進めて行きましょう。
新たなディレクトリ構造
読み込み方法
require_once(__DIR__.'【記述ファイルからの相対パス※頭にスラッシュ有り】');
一旦上記の構造で進めていきます。公開ディレクトリだのアクセス制限が気になる人はもっとキレイに配置するかフレームワークでも使いましょう。
2進化ポケモンの実装
ピカチュウのおかげである程度機能が整ったので、今回は新たにポケモンを増やします。その映えある第1号に選ばれたのが、全国図鑑最上位に君臨するカエル三兄弟ことフシギダネさん一家です。
前回進化のシステムを導入したので、最終進化までセットで加えていきます。ステータスに関しては、ピカチュウ一家と同じく以下のデータを参考にします。
種族値 → 執筆時段階での最新シリーズ
覚える技 → 初代
ポケモンの追加
それでは、進化前のフシギダネから順に追加していきます。ピカチュウのクラスを参考にしながら、フシギダネのクラスを作成しましょう。
フシギダネ(/Classes/Pokemon/Fushigidane.php)
<?php
require_once(__DIR__.'/../Pokemon.php');
require_once(__DIR__.'/Fushigisou.php');
// フシギダネ
class Fushigidane extends Pokemon
{
/**
* 正式名称
* @var string(min:1 max:5)
*/
protected $name = 'フシギダネ';
/**
* 初期レベル
* @var array
*/
protected $default_level = [
5
];
/**
* レベルアップで覚える技
* @var array
*/
protected $level_move = [
[1, 'たいあたり'],
[1, 'なきごえ'],
[7, 'やどりぎのタネ'],
[13, 'つるのムチ'],
[20, 'どくのこな'],
[27, 'はっぱカッター'],
[34, 'せいちょう'],
[41, 'ねむりごな'],
[48, 'ソーラービーム'],
];
/**
* 種族値
* @var array
*/
protected $base_stats = [
'HP' => 45,
'こうげき' => 49,
'ぼうぎょ' => 49,
'とくこう' => 65,
'とくぼう' => 65,
'すばやさ' => 45,
];
/**
* インスタンス作成時に実行される処理
*
* @return void
*/
public function __construct()
{
$this->setLevel();
$this->setDefaultExp();
$this->setDefaultMove();
$this->setIv();
echo '<p>フシギダネをゲットした</p>';
}
/**
* 進化 → フシギソウ
*
* @return Classes\Pokemon\Fushigisou
*/
public function evolve()
{
return new Fushigisou($this);
}
}
※ポケモンの名前を英語で統一させようと考えていましたが、フシギダネの英語名は「Bulbasaur」で、増えていくと絶対に判別できなくなると判断したので断念しました
フシギソウはまだ作成していませんが、作成する前提でプログラムを組んでいきます。
親コンストラクタの活用
フシギダネのクラスを作りましたが、1点気になる箇所がありますね。それはコンストラクタ(__construct)の処理です。
/**
* インスタンス作成時に実行される処理
*
* @return void
*/
public function __construct()
{
$this->setLevel();
$this->setDefaultExp();
$this->setDefaultMove();
$this->setIv();
echo '<p>フシギダネをゲットした</p>';
}
インスタンス化した際の一連の処理は、基本的に全ポケモン共通です。進化の分岐はありますが、同じ処理はできる限りまとめて置くほうが保守性は高まります。なので、親クラスであるポケモンクラス(Pokemon)のコンストラクタを活用します。
ポケモン(/Classes/Pokemon.php)
/**
* インスタンス作成時に実行される処理
*
* @return void
*/
public function __construct()
{
$this->setLevel();
$this->setDefaultExp();
$this->setDefaultMove();
$this->setIv();
echo '<p>'.$this->name.'をゲットした</p>';
}
もし子クラスにコンストラクタがなく、親のコンストラクタが存在している場合は、親のコンストラクタが呼び出されます。もしどちらも記述されている場合は、子が優先されます。
なので、基本的には親のコンストラクタを使用、例外処理が必要になるポケモンに関しては子のコンストラクタを使用しましょう。
コンストラクタ(PHP.net)
子クラスがコンストラクタを有している場合、親クラスのコンストラクタが 暗黙の内にコールされることはありません。
進化前の判定
進化についても、基本的な処理は同じです。なので親であるポケモンのコンストラクタで分岐させるのが好ましいですね。そのためには、正しい進化元かどうかを判別するためのプロパティが必要になります。進化ポケモンのクラスにchild_classというプロパティを追加しましょう。以下、フシギソウ(Fushigisou)のクラスです。
フシギソウ(/Classes/Pokemon/Fushigisou.php)
<?php
require_once(__DIR__.'/../Pokemon.php');
require_once(__DIR__.'/Fushigibana.php');
// フシギソウ
class Fushigisou extends Pokemon
{
/**
* 正式名称
* @var string(min:1 max:5)
*/
protected $name = 'フシギソウ';
/**
* 進化前(クラス名)
* @var string
*/
protected $child_class = 'Fushigidane';
/**
* 初期レベル
* @var array
*/
protected $default_level = [
16
];
/**
* レベルアップで覚える技
* @var array
*/
protected $level_move = [
[1, 'たいあたり'],
[1, 'なきごえ'],
[1, 'やどりぎのタネ'],
[7, 'やどりぎのタネ'],
[13, 'つるのムチ'],
[22, 'どくのこな'],
[30, 'はっぱカッター'],
[38, 'せいちょう'],
[46, 'ねむりごな'],
[54, 'ソーラービーム'],
];
/**
* 種族値
* @var array
*/
protected $base_stats = [
'HP' => 60,
'こうげき' => 62,
'ぼうぎょ' => 63,
'とくこう' => 80,
'とくぼう' => 80,
'すばやさ' => 60,
];
/**
* 進化 → フシギソウ
*
* @return Classes\Pokemon\Fushigibana
*/
public function evolve()
{
return new Fushigibana($this);
}
}
それでは新しく追加したプロパティを見てみましょう。
/**
* 進化前(クラス名)
* @var string
*/
protected $child_class = 'Fushigidane';
フシギソウの進化前はフシギダネです。そして判別するためにはクラス名が必要になるので、フシギダネのクラス名である「Fushigidane」をセットしています。前回作成したライチュウには「Pikachu」をセットしておきましょう。
次に、ポケモンクラスのコンストラクタ内に進化の判定を追加します。
ポケモン(/Classes/Pokemon.php)
/**
* インスタンス作成時に実行される処理
*
* @param object|null
* @return void
*/
public function __construct($before=null)
{
// 進化前のポケモンと一致しているかチェック
if(is_a($before, $this->child_class ?? null)){
// 進化した際の処理
$this->takeOverAbility($before);
echo '<p>'.$this->name.'に進化した</p>';
}else{
// 捕まえた際の処理
$this->setLevel();
$this->setDefaultExp();
$this->setDefaultMove();
$this->setIv();
echo '<p>'.$this->name.'をゲットした</p>';
}
}
変更された条件分岐の部分を見てみましょう。
if(is_a($before, $this->child_class ?? null)){
is_a(クラスの判定)の第2引数(クラス名)に、先程追加したchild_classのプロパティを指定しています。これで、現在インスタンスを呼び出されてたポケモンが$beforeで受け取ったポケモンと一致しているかを判定しています。
ただし、ピカチュウやフシギダネは進化前を持たないため、プロパティを設定する必要ありません。その判定用としてNull合体演算子を使用して、なければnullをセットする仕様にしています。
これで進化時の判定を追加することができました。残りのフシギバナのクラスを作成して、出力をしてみましょう。
フシギバナ(/Classes/Pokemon/Fushigibana.php)
<?php
require_once(__DIR__.'/../Pokemon.php');
// フシギバナ
class Fushigibana extends Pokemon
{
/**
* 正式名称
* @var string(min:1 max:5)
*/
protected $name = 'フシギバナ';
/**
* 進化前(クラス名)
* @var string
*/
protected $child_class = 'Fushigisou';
/**
* 初期レベル
* @var array
*/
protected $default_level = [
32
];
/**
* レベルアップで覚える技
* @var array
*/
protected $level_move = [
[1, 'たいあたり'],
[1, 'なきごえ'],
[1, 'やどりぎのタネ'],
[1, 'つるのムチ'],
[7, 'やどりぎのタネ'],
[13, 'つるのムチ'],
[22, 'どくのこな'],
[30, 'はっぱカッター'],
[43, 'せいちょう'],
[55, 'ねむりごな'],
[65, 'ソーラービーム'],
];
/**
* 種族値
* @var array
*/
protected $base_stats = [
'HP' => 80,
'こうげき' => 82,
'ぼうぎょ' => 83,
'とくこう' => 100,
'とくぼう' => 100,
'すばやさ' => 80,
];
}
出力ファイル(/index.php)
<?php
require_once(__DIR__.'/Classes/Pokemon/Fushigidane.php');
// HTML出力用関数
function echoKeyToVal($array)
{
foreach($array as $key => $val){
echo '<p>'.$key.':'.$val.'</p>';
}
}
// フシギダネをゲット
$pokemon = new Fushigidane;
echoKeyToVal($pokemon->getDetails());
echoKeyToVal($pokemon->getStats());
// フシギソウに進化
$pokemon = $pokemon->evolve();
echoKeyToVal($pokemon->getDetails());
echoKeyToVal($pokemon->getStats());
// フシギバナに進化
$pokemon = $pokemon->evolve();
echoKeyToVal($pokemon->getDetails());
echoKeyToVal($pokemon->getStats());
?>
※ステータスや詳細の出力を毎回書くのが面倒になったので、出力用の関数を作成して使用しています
# 出力結果
フシギダネをゲットした
正式名称:フシギダネ
ニックネーム:フシギダネ
現在のレベル:5
覚えている技:たいあたり,なきごえ
現在の経験値:125
次のレベルまでに必要な経験値:91
HP:20
こうげき:10
ぼうぎょ:11
とくこう:12
とくぼう:12
すばやさ:9
フシギソウに進化した
正式名称:フシギソウ
ニックネーム:フシギソウ
現在のレベル:5
覚えている技:たいあたり,なきごえ
現在の経験値:125
次のレベルまでに必要な経験値:91
HP:21
こうげき:12
ぼうぎょ:12
とくこう:13
とくぼう:13
すばやさ:11
フシギバナに進化した
正式名称:フシギバナ
ニックネーム:フシギバナ
現在のレベル:5
覚えている技:たいあたり,なきごえ
現在の経験値:125
次のレベルまでに必要な経験値:91
HP:23
こうげき:14
ぼうぎょ:14
とくこう:15
とくぼう:15
すばやさ:13
これでフシギダネからフシギバナまで、無事進化することができました。
サンプルコードの配布
第8回終了時点のPHPポケモンのコードをGitHubより配布します。好きにダウンロードして使用してください。
コードは毎回終了時に配布するわけではありません。ある程度溜まったら、そのタイミングで終了時点のコードを配布予定です。ぜひ学習用としてお役立てください。
まとめ
いかがだったでしょうか。
今回のPHPポケモンは「2進化ポケモン実装編」についてご紹介しました。
好きなポケモンがいる人は、試しに追加してみてください。言語を問わず、プログラミングの学習は楽しみながらすることが習得の近道ですので、ぜひ参考にしてくださいね。