ポケモン預かりシステムとは
ポケモンは手持ち(パーティー)に6匹しか入れることができません。そのため、ポケモンを捕まえた際にその上限に達していれば、ボックスへ転送するという仕組みをPHPポケモンでも実装していきます。これが、ポケモン預かりシステムです。
今回は前段階であるボックスの仕様決めをメインに解説します。
機能について
ボックスを作成するにあたって機能面について確認していきましょう。世代によってはアイテムやメールの管理もできますが、アイテムはカテゴリ分けしてカバンへ入れられるようにしており、わざわざ預けて管理する必要もないので現段階では不要とします。
預ける
ポケモンを預ける方法は、「手持ちが6匹の状態で、新しく1匹を捕まえた際の自動転送」と、「ボックスに接続してパーティーからポケモンを預ける」の2通りです。
第1世代ではポケモンを預けた際に体力や状態異常の回復処理はされませんでしたが、PHPポケモンでは第2世代以降を参考に全回復の処理は実装します。
また、ボックスに預ける際も通常ルート外からのアクセスを防ぐために、ポケモンの立場が味方(friend)のみに制限をかけておきます。
引き取る
預けたポケモンをパーティーへ加えるためには、ボックスへアクセスしてポケモンを引き取るという手順になります。
手持ちに既に6匹いれば追加することができず、1匹を預けてから引き取るという手順を踏む必要があります。第2世代ではボックス整理、第3世代からはポケモンを預けずに入れ替えることができるなど操作性は向上し、自由度も高い機能となっていました。ですが、処理自体が複雑になる可能性を考慮し、PHPポケモンでは処理それぞれを独立させて実装予定です。
処理速度問題
データベースを使用していないPHPポケモンでは、ボックスを作成するにあたって、1点気になるポイントがあります。それは「膨大なデータの暗号化と復号化」についてです。
こちらの問題点をまとめながら、検証していきましょう。
暗号化と復号化
画面移管時にはセッション経由でデータを渡しています。そのため、オブジェクト(インスタンス)をそのまま送ることができず、毎回暗号化(シリアライズ)して文字列として格納しています。画面再開時には復号化(アンシリアライズ)して再度使用できる状態にしていますが、これをポケモンボックスのように膨大なオブジェクトを抱えた配列に対して行えば膨大な処理時間がかかることが予想されます。
そこで今回検証するのは、データをシリアライズ(暗号化)して文字列として格納するのと、オブジェクトとして格納するのでは、どれぐらいの速度差があるのかです。
ポケモンボックスはクラスと作成し、その1つのプロパティ(配列)のポケモン情報を格納していくことになります。ですが、このポケモンボックスのクラスを復号化、または暗号化すれば、中に保管されているものがオブジェクトか文字列かで差がでることが予想されます。
もしこの差がごく小さなものであれば、オブジェクトで格納しても問題ありませんが、明らかな差が出れば、ポケモン自体は常に暗号化された状態で保管しておき、必要なとき(ボックスへのアクセス時)にだけ復号化するようにしなければなりません。
なので、上記検証をするためにテストコードを使って速度計算をしてみました。
<?php
class TestChild
{
public $name = '子テスト';
public $desc = '子テスト説明';
}
class Test
{
public $tests = [];
public function __construct($serialize=false)
{
for($i=0;$i<10000;$i++){
if($serialize){
// シリアライズ(暗号化)して格納
$test = new TestChild;
$this->tests[] = serialize($test);
}else{
// オブジェクトそのまま格納
$this->tests[] = new TestChild;
}
}
}
}
$start = microtime(true);
// 計測する処理 ====
$test = new Test(); #インスタンス化
$serialize = serialize($test);
$un = unserialize($serialize);
// ====
$time = microtime(true) - $start;
echo "{$time} 秒"; # かかった時間
計測する処理のインスタンス化時に引数で暗号化・復号化の分岐をさせています。ポケモンオブジェクトのような複雑なクラスで検証するのは手間なので、今回は物量でカバーするため、forを使って1万個の子オブジェクトを格納しています。
まずは引数なし(オブジェクトのまま格納)の速度結果です。
0.018399953842163 秒
次に、引数trueのシリアライズ(暗号化)して文字列として格納した際の速度結果です。
0.007889986038208 秒
若干のばらつきはありますが、暗号化すると速度を1/2程度に抑えることができました。なので、膨大なポケモンオブジェクトが格納される可能性のあるボックスは、基本的に暗号化した状態で保管するようにしておき、ボックスへアクセスした場合のみ復号化するような仕様で作成していきます。
※実際のポケモンでもボックスアクセス時にはセーブや切り替えという機能があるので、似たような理由が存在しているのかも知れません。言語の違いもあるため実際のところはわかりませんが、実際に作る側に回ってみるといろいろな気付きがあります
まとめ
いかがだったでしょうか。
今回のPHPポケモンでは、ポケモン転送システムについてご紹介しました。
次回からはいよいよ機能実装を進めていきますので、乞うご期待ください。