両隣のポケモンを判別する
パーティーの中からID指定でポケモンを特定するためのメソッドは実装されていましたが、その両隣にどんなポケモンが控えているのかを判別する手段がありませんでしたね。
なので、今回は両隣のポケモンを判別するためのメソッドを準備して活用していきましょう。
パーティー
まずはパーティーの両隣についてです。パーティーのポケモンはpartyプロパティに配列として添字で格納されています。ポケモンの並び替え等をした際にはarray_valuesで採番しているため、番号は0番から連続するものとして常に格納されているものという前提条件で考えていきます。
前のポケモン
ID指定したポケモンの手前には、添字―1のポケモンがいます。なので、もしID指定したポケモンが見つからなかったり、そのポケモンの添字が0であれば、手前にはポケモンがいないということになります。
これらを踏まえて、以下のメソッドを見ていきましょう。
プレイヤーパーティー操作用トレイト(/App/Traits/Class/Player/ClassPlayerPartyTrait.php)
/**
* 指定したポケモンの手前のポケモン番号を取得
* @param id:string
* @return integer|false
*/
public function prevPartner(string $id)
{
$partner = array_filter($this->party, function($partner) use($id){
return $partner->getId() === $id;
});
if($order = array_key_first($partner)){
// 1引いた番号を返却
return $this->party[--$order];
}else{
// 0番(最初)または見つからなければnull
return null;
}
}
array_filterで抽出した結果は、キーも維持された状態になります。そのため、抽出結果の最初の添字をarra_key_firstで抽出すれば、ID指定したポケモンの番号が判別可能です。
その値が0または存在しない(null)であれば、見つからなかったものとしてnullを返却、1以上の数値が返ってくれば、―1した添字のポケモンをパーティーから選んで返却しています。
次のポケモン
次のポケモンを判別するためのメソッド自体も、prevPartnerと同じ要領で確認をしていきます。
プレイヤーパーティー操作用トレイト(/App/Traits/Class/Player/ClassPlayerPartyTrait.php)
/**
* 指定したポケモンの次のポケモン番号を取得
* @param id:string
* @return object::Pokemon|false
*/
public function nextPartner(string $id)
{
$partner = array_filter($this->party, function($partner) use($id){
return $partner->getId() === $id;
});
$order = array_key_first($partner);
if(
is_null($order) ||
array_key_last($this->party) === $order
){
// 最終番号または見つからなければnull
return null;
}else{
// 次のポケモン情報を返却
return $this->party[++$order];
}
}
ID指定したポケモンが見つからない(null)またはパーティー内の最後の位置(array_key_last)と一致するのであれば、次のポケモンはいないということになります。この条件で分岐を作成し、もし上記条件に一致しなければ、パーティー内から添字+1のポケモンを返却しています。
ポケモン預かりシステム
パーティー内での前後以外にも、ボックスにいるポケモンの前後も知りたい場面がいくつか出てきます。なので、こちらもパーティーの抽出と同じ要領で前後の判別をしていきましょう。
ポケモン預かりシステム ポケモン操作用トレイト(/App/Traits/Class/Pokebox/ClassPokeboxPokemonTrait.php)
/**
* 指定されたポケモンの手前にいるポケモン情報を取得する
* @param id:string
* @return object::Pokemon|null
*/
public function prevPokemon(string $id)
{
// ポケモンIDを使って取得
$pokemon = array_filter($this->pokebox[$this->selected], function($pokemon) use($id){
return $pokemon['id'] === $id;
});
// 先頭でなければ手前の番号のポケモン情報を返却
if($order = array_key_first($pokemon)){
// 復号化して返却
return unserializeObject(
$this->pokebox[$this->selected][--$order]['object']
);
}else{
return null;
}
}
/**
* 指定されたポケモンの手前にいるポケモン情報を取得する
* @param id:string
* @return object::Pokemon|null
*/
public function nextPokemon(string $id)
{
// ポケモンIDを使って取得
$pokemon = array_filter($this->pokebox[$this->selected], function($pokemon) use($id){
return $pokemon['id'] === $id;
});
// 末尾でなければ次の番号のポケモン情報を返却
$order = array_key_first($pokemon);
if(
!is_null($order) &&
array_key_last($this->pokebox[$this->selected]) !== $order
){
// 復号化して返却
return unserializeObject(
$this->pokebox[$this->selected][++$order]['object']
);
}else{
return null;
}
}
ボックス内のポケモンは、選択中のボックスに限定して判別しています。パーティーと異なりシリアライズされていない状態で格納されているため、もし見つかった際はアンシリアライズしてから返却しています。
パーティーでも、ポケモン預かりシステムでも同じく、変更があった際には必ず採番するようにしなければ、この方法では特定することができなくなります。ボックスからパーティーへ、またはその逆、ポケモンの並び替え等をした際には、必ずarray_valuesを挟んでから格納するようにしておきましょう。
詳細モーダルへの追加
前後のポケモンが判別できるようになったので、いざ画面への実装です。ポケモンの詳細を開いた際に、次のポケモンの状態を閲覧するには一度モーダルを閉じる必要があり、操作性の悪さを感じたので、詳細モーダルの下部に移動用のアイコンを設置しましょう。
ポケモン詳細モーダル(/Resources/Partials/Common/Modals/pokemon-details.php)
<div class="modal-footer justify-content-between">
<?php # 前のポケモン ?>
<?php
if(getPageName() === 'pokebox'){
$prev = player()->prevPartner($pokemon->getId()) ?? pokebox()->prevPokemon($pokemon->getId());
}else{
$prev = player()->prevPartner($pokemon->getId());
}
?>
<?php if($prev): ?>
<img src="<?=$prev->base64('mini')?>"
alt="<?=$prev::NAME?>"
class="cursor-pointer"
data-toggle="modal"
data-dubble_modal="true"
data-hide_modal="#pokemon<?=$pokemon->getId()?>-details-modal"
data-target="#pokemon<?=$prev->getId()?>-details-modal" />
<?php else: ?>
<span></span>
<?php endif; ?>
<?php # 次のポケモン ?>
<?php
if(getPageName() === 'pokebox'){
$next = player()->nextPartner($pokemon->getId()) ?? pokebox()->nextPokemon($pokemon->getId());
}else{
$next = player()->nextPartner($pokemon->getId());
}
?>
<?php if($next): ?>
<img src="<?=$next->base64('mini')?>"
alt="<?=$next::NAME?>"
class="cursor-pointer"
data-toggle="modal"
data-dubble_modal="true"
data-hide_modal="#pokemon<?=$pokemon->getId()?>-details-modal"
data-target="#pokemon<?=$next->getId()?>-details-modal" />
<?php else: ?>
<span></span>
<?php endif; ?>
</div>
詳細モーダルはポケモン預かりシステムと併用しているため、$prev、$next共にパーティーから値が取得できなければ、ボックスからポケモンを取得しています。
モーダルの切り替え
詳細モーダルの行き来ができるようになりましたが、モーダルを開き続けると何重にも重り続けてしまいます。それを回避するためにも、モーダルの切り替え判定を追加し、指定されたモーダルを閉じるという処理をjsに追加しましょう。
/**
* 指定したモーダルの非表示処理
* @function on:click
*/
var hideModalInit = function() {
$('[data-hide_modal]').on('click', function() {
var modal = $(this).data('hide_modal');
$(modal).modal('hide');
});
}
モーダル起動はBootstrap4の機能で、そのまま必要なパラメーターを埋め込むことで解決しています。しかし、指定したモーダルだけを閉じることはできないので、新たにdata-hide_modalというパラメーターをノードに追加、指定されたモーダルを終了させています。
それでは動作確認をしてみましょう。
両隣のポケモンへ移動できるようになりましたね。
これで詳細モーダルの切り替えが完了です。
まとめ
いかがだったでしょうか。
今回のPHPポケモンでは「配列の隣の要素(添字連番)」についてご紹介しました。
現在プログラミング学習に取り組んでいる方や、興味を持っている方は、是非参考にしてみてくださいね。