アイテムによる進化
前回作成した、進化アイテムによる構成の続きです。
進化アイテムとして「かみなりのいし」、ピカチュウの進化判定を作成したので、アイテムの使用から進化処理までを作成、実装します。
今回作成する処理は以下の2点です。
- アイテムの使用判定
- 進化画面への移管
それでは1つずつ見ていきましょう。
フロント画面の作成
進化の石は、該当ポケモン以外に使っても意味がありません。どのポケモンに使用できるかなどをひと目で分かるように、PHP側で用意した対象ポケモンを、フロント側で判定する必要があります。
まず、判定の有無がわかるように「ポケモン一覧」にバッジを作成しましょう。
アイテム使用時のポケモン一覧モーダル(/Resources/Partials/Common/Modals/Item/item-use-friend.php)
<?php foreach(player()->getParty() as $order => $party): ?>
<div class="row bg-hover-light pokemon-row py-1" data-pokemon="<?=$order?>" data-class="<?=get_class($party)?>">
<div class="col-3 text-center">
<img src="<?=$party->base64('mini')?>" alt="<?=$party::NAME?>">
</div>
<div class="col-9">
<div class="row">
<div class="col-12">
<?=$party->getNickname()?>
</div>
</div>
<div class="row">
<div class="col-10">
<div class="progress rounded-pill bg-gray" style="height:4px;">
<div class="progress-bar bg-<?=$party->getRemainingHp('color')?>"
role="progressbar"
style="width:<?=$party->getRemainingHp('per')?>%;"
aria-valuenow="<?=$party->getRemainingHp()?>"
aria-valuemin="0"
aria-valuemax="<?=$party->getStats('H')?>">
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-8">
<?=$party->getRemainingHp()?> / <?=$party->getStats('H')?>
</div>
<div class="col-4">
Lv.<?=$party->getLevel()?>
</div>
</div>
</div>
<div class="col-12">
<span class="badge badge-secondary d-soft-none" data-is_use="false">使えません</span>
<span class="badge badge-php-dark d-soft-none" data-is_use="true">使えます</span>
</div>
</div>
<?php endforeach; ?>
最下部に非表示のバッジを追加、ポケモンの行に判別用の「ポケモンクラス」をdata-classに持たせました。
次に、前回作成したアイテムの対象ポケモン配列を、アイテム行にjson_encodeでセットします。
アイテムモーダル用アイテム行(/Resources/Partials/Common/Modals/Item/item-row.php)
<?php # 利用可能 ?>
<tr data-description="<?=$item['class']::DESCRIPTION?>"
data-name="<?=$item['class']::NAME?>"
data-category="<?=$category?>"
data-target="<?=$item['class']::TARGET?>"
data-use="<?=var_export($item['class']::allowUsed(getPageName()), true)?>"
data-trash="<?=var_export($item['class']::allowTrashed(), true)?>"
data-owned="<?=$item['count']?>"
data-order="<?=$item['order']?>"
<?php # 使用できるポケモン ?>
<?php if($item['class']::POKEMON): ?>
data-pokemon='<?=json_encode($item['class']::POKEMON)?>'
<?php endif; ?>
class="item-row">
<td class="w-75">
<img src="/Assets/img/item/class/<?=$item['class']?>.png" alt="<?=$item['class']::NAME?>" class="mr-1" />
<?=$item['class']::NAME?>
</td>
<td class="w-25 text-right"><?=$item['count']?> 個</td>
</tr>
これで、アイテムを選択した際に対象ポケモンの判別するための値が揃いました。次にJavaScriptによる分岐を作成しましょう。
アイテム用JS(/Public/Assets/js/Common/item.js)
/**
* 「使う」の処理(ポケモン)
* @function on:click
* @return void
*/
var clickItemUseFriendInit = function(){
$('[data-button="use"][data-item_target="friend"]').on('click', function(){
// アイテムカテゴリ取得
var category = $(this).parent().data('category');
// 選択されたアイテムノードを取得
var tr = $('tr[data-category="' + category + '"].active');
var name = tr.data('name');
var order = tr.data('order');
// 使用できるポケモン
var pokemon = $(tr).data('pokemon');
// フォームを取得
var form = $('form#item-use-friend-form');
// アイテム名とアイテム番号をセット
$('#item-use-name').text(name);
form.find('[name="order"]').val(order);
// 使用できるポケモンの判定
if(pokemon){
$('#item-use-friend-modal .pokemon-row').each(function(){
// 使用できるポケモンに該当しているかの確認
var result = 0 <= $.inArray($(this).data('class'), pokemon);
$(this).find('[data-is_use="' + result + '"]')
.show();
$(this).find('[data-is_use="' + !result + '"]')
.hide();
});
}
});
}
/**
* 「ポケモンに使う」モーダルが閉じた際の処理
* @function modal:hide
* @return void
*/
var closeItemUseFriendModalInit = function(){
$('#item-use-friend-modal').on('hide.bs.modal', function(){
// 使用可否のバッジを全て非表示にする
$(this).find('[data-is_use]').hide();
});
}
アイテム使用ボタンが押された際に、対象ポケモンかどうかを判別しています。ifによる判定でも構いませんが、今回はdata-is_useにboolean値をセットしているので、そのまま文字列として当て込むことで使用可否を判別させました。
他のアイテムではバッチ自体が不要のため、モーダルが閉じた際にはどちらも非表示(初期状態)へ戻すための関数も追加しました。
進化判定の作成
フロント側の処理が整ったので、アイテム使用時に進化画面へ移管させるための処理を追加しましょう。
アイテム使用トレイト(/App/Traits/Service/Item/ServiceItemUseTrait.php)
<?php
// アイテムを使用する処理
trait ServiceItemUseTrait
{
/**
* 使う(対象:ポケモン)
* @param item:string
* @return boolean
*/
protected function useItemToFriend(string $item): bool
{
// パーティー取得
$party = player()->getParty();
// パーティーに指定されたポケモンが存在しているかどうか確認
if(!isset($party[request('pokemon')])){
response()->setMessage('使っても効果がないよ');
if(getPageName() === 'home'){
response()->setToastr('error', '使っても効果がないよ');
}
return false;
}
// アイテム効果を使用
$result = $item::effects($party[request('pokemon')]);
// メッセージが返ってきていればセット
if(isset($result['message'])){
response()->setMessage($result['message']);
if(getPageName() === 'home'){
response()->setToastr(
($result['result'] ?? false) ? 'success' : 'error',
$result['message']
);
}
}
// アクションの確認(進化判定等)
if(
isset($result['action']) &&
$result['result'] ?? false
){
// レスポンスにアクションをセット
response()->setResponse($result['action'], 'action');
}
// 描画処理(バトルポケモンへのアイテム使用であれば)
if(
getPageName() === 'battle' &&
(int)request('pokemon') === battle_state()->getOrder()
){
// HPバーの変動処理
if(isset($result['hpbar'])){
response()->setResponse([
'param' => $result['hpbar'],
'action' => 'hpbar',
'target' => 'friend',
], $this->use_msg_id);
}
}
return $result['result'];
}
味方へのアイテム使用時に判定を追加しました。進化アイテムでは結果(result)と一緒にactionを返却しています。resultがtrue且つaction値が返って来ていればresponseに格納してコントローラーへ伝えます。
この時点で使用したポケモンの進化フラグはtrueになっているので、コントローラーでは返ってきたレスポンスを確認して、もし値がセットされていればリダイレクトするだけです。
ホームコントローラー(/App/Controllers/Home/HomeController.php)
// branchメソッド内
/******************************************
* どうぐ
*/
case 'item':
$service = new ItemService;
$service->execute();
// アクション有り
if(response()->getResponse('action')){
$_SESSION['__route'] = response()->getResponse('action');
// 画面移管
$this->redirect();
}
break;
これで、actionの値に合わせたリダイレクトが可能です。では実際の動きを見てみましょう。
103回を経て、無事ピカチュウがライチュウに進化できました。これでアイテムによる進化処理の実装は完了です。
まとめ
いかがだったでしょうか。
今回は「アイテムによるポケモンの進化」の実装方法をご紹介しました。
進化処理や、アイテムの使用については、トレイト分けしたり様々なパターンに合わせた処理の柔軟性を考慮しながら作成しているため、実装が比較的簡単にできるようになっています。もし、レベルアップによる進化が同一処理で作成されていると、その処理自体は簡単でわかりやすく書けるかも知れませんが、別ルートからの進化を行う際に、同じような処理を新しく作成しなければなりません。仕様決めや設計の大切さが、開発を進めていくことでわかりますね。
現在プログラミング学習に取り組んでいる方や、興味を持っている人は、ぜひ参考にしてみてくださいね。