プログラミング

経験値分配編 PHPポケモン 89

PHP PHPポケモン ポケモン
経験値分配編 PHPポケモン 89

経験値の分配とは

大型アップデート後、最初の追加機能は「経験値の分配」についてです。

ポケモンの入れ替えができるようになりましたが、経験値をもらえるのは現在フィニッシャーのみとなっており、レベルの低いポケモンを育てるのが困難な状態です。なので、ゲームバランスを整えるためにも、まず経験値周りの処理から見直しをしていきましょう。

 

 経験値の計算式

分配の計算式についてですが、世代によって微妙に異なっています。最新の第8世代ではポケモン全てに経験値が割り振られたり、世代によっては選出されたポケモンそれぞれに計算式が適用される場合もあります。

ですが、この点においては旧世代を参考にしながらオリジナルの計算式として、基本となる経験値量を選出されたポケモン数に分配、その後レベル補正をかけるという仕組みで実装していきます。

 

まずはPHPポケモンで現在使用している経験値の算出式を見てみましょう。

 

経験値の計算式(旧)

EXP × LM^2.5 + 1

  • EXP 倒されたポケモンのレベル × 倒されたポケモンの基礎経験値 ÷ 5
  • LM レベル補正 (2L + 10) / (L + Lp + 10)
  • L 倒されたポケモンのレベル
  • Lp 倒したポケモンのレベル

 

レベル補正が掛かる前のEXPが分配される基本の経験値となります。これを選出されたポケモン数で割るため、分配式は以下の通りです。

 

経験値の計算式(新)

EXP / count × LM^2.5 + 1

  • count 戦闘に参加したポケモンの数

 

これで、均等に経験値を分け合い且つ、レベル補正はそれぞれに依存させることができます。

 

選出ポケモン情報の保管

選出されたポケモンの記録は、バトル状態クラス(battle_state)を使って管理します。保管用のプロパティとしてfought_ordersを初期値配列で作成、ここに選出されたポケモン番号を格納していきます。

 

バトル状態ポケモン関係トレイト(/App/Traits/Class/BattleState/ClassBattleStatePokemonTrait.php
/**
* 戦闘に参加しているポケモン番号の格納(private)
* @param order:integer
* @return void
*/
private function setOrder(int $order): void
{
    // 番号をプロパティへ格納
    $this->order = $order;
    // 戦闘に参加したポケモンリストに格納
    if(!in_array($order, $this->fought_orders, true)){
        $this->fought_orders[] = $order;
    }
}

 

選出されたポケモンが増えるタイミングは、オーダーセット時です。なので、オーダーをセットする処理をメソッド管理にして、このタイミングに選出リストへ加えていきます。

同じポケモンが再度選出される可能性も考慮して、in_arrayで重複回避をしています

 

選出されたとしても、そのポケモンが戦闘不能になっていれば経験値は貰えません。ですが、アイテムなどを使ってひんし状態が解除されれば経験値をもらうことができます。

なので、瀕死状態の確認はポケモン番号を取得する際にフィルターがけすることで判定します。

/**
* 経験値を貰える権利があるポケモン番号の取得
* @return array
*/
public function getEntitledExpOrders(): array
{
    /**
    * 現在戦闘中のポケモンを先頭にする
    */
    // 現在戦闘中のポケモン番号を削除(次のarray_unshiftが破壊的な関数のため変数へ格納)
    $fought_orders = array_diff($this->fought_orders, [$this->order]);
    // 先頭に現在のポケモン番号を追加
    array_unshift($fought_orders,  $this->order);
    // 戦闘可能状態でフィルターにかけて返却
    return array_filter(
        $fought_orders,
        function($order){
            return player()->getPartner($order)->isFight();
        }
    );
}

 

経験値取得の順番ですが、フィニッシャーが最初に来るように、一度array_diffを使って現在のポケモン番号を削除、array_unshiftで再度先頭へ追加しています。

 

※フィニッシャーが最後にならなくても不具合自体は発生しませんが、本作同様の手順で処理が行われるようにしています。

また、経験値バーの描画処理などは、現在のポケモン番号とフィニッシャーが一致していたときのみ生成されるように分岐させました。

 

それでは、実際の動きを進化処理まで含めて見てみましょう。

 

進化処理の作成段階では複数を想定して組んでいたため、問題なく処理されることが確認できました。

以上で経験値の分配機能は完成です。

 

技習得ポケモン複数発生時の対策

今まではポケモンが1匹のみを想定していたため、同時に技習得が発生した際に「バトル中のポケモン」を対象に処理を行なっていました。ですが、経験値の分配により同時に技習得が発生する可能性が出てきたため、どのポケモンの技を書き換えるかを判定する必要が出てきました。

 

例(現段階の処理)

ピカチュウ(フィニッシャー)

フシギダネ(選出:つるのムチを覚えたい)

ピカチュウが「つるのムチ」を覚えてしまう

 

これを回避するためにも、技習得のレスポンスに対してポケモンのIDを持たせ、習得時のポケモン選出をこのIDを使って検索したポケモンのオブジェクトに対して行います。

 

ポケモンクラスチェック用トレイト(/App/Traits/Class/Pokemon/ClassPokemonCheckTrait.php
// checkLevelMoveメソッド内
/**
* 技選択用モーダルの返却
*/
// メッセージIDを生成
$msg_id = response()->issueMsgId();
// レベルアップメッセージ
response()->setMessage($this->getNickName().'は'.$move->getName().'を覚えたい');
response()->setMessage('しかし技を4つ覚えるので精一杯だ');
response()->setMessage($move->getName().'の代わりに他の技を忘れさせますか?', $msg_id);
// レスポンスデータをセット
response()->setResponse([
    'toggle' => 'modal',
    'target' => '#'.$msg_id.'-modal',
    'move' => $move_class,
    'pokemon_id' => $this->id  #追加したポケモン判別用ID
], $msg_id);
// モーダル用のレスポンスをセット
response()->setModal([
    'id' => $msg_id,
    'modal' => 'acquire-move',
    'new_move' => $move,
    'pokemon_id' => $this->id
]);
// 諦めメッセージを事前に用意しておく
response()->setMessage($this->getNickName().'は'.$move->getName().'を覚えるのを諦めた');

 

技習得サービス(/App/Services/Battle/LearnMoveService.php
/**
* 技の置き換え
* @return void
*/
private function replaceMove()
{
    // 技を習得する対象のポケモンのIDを旧レスポンスから取得(交代したポケモンを想定)
    $pokemon = player()->getPartner(
        $this->before_responses[request('param.id')]['pokemon_id'], 'id'
    );
    // 忘れる技を取得
    $forget_move = $pokemon
    ->getMove(request('param.forget'));
    // 覚えさせる技を旧レスポンスから取得
    $new_move = new $this->before_responses[request('param.id')]['move'];
    // 技を覚えさせる
    $pokemon
    ->setMove($new_move, request('param.forget'));
    // メッセージの返却
    response()->setMessage('1 2の ……ポカン!');
    response()->setMessage($pokemon->getNickname().'は、'.$forget_move->getName().'の使い方をキレイに忘れた!そして......');
    response()->setMessage($pokemon->getNickname().'は新しく、'.$new_move->getName().'を覚えた!');
}

 

ユーザー入力によるバグ回避

ブラウザを使ったゲームにおいて気をつけて置かなければならないのが「ユーザー入力」による値の想定です。例えば、デベロッパーツールから値を直接変更すれば、インターフェースで制限を設けていたとしても「予期せぬ値」がPOSTされてきます

もちろん、無理な操作でデータが消失することに関してはプレイヤー側の責任として問題ありませんが、正常に処理が通ってしまうことが一番の問題となります。

 

例えば、今回のポケモンを判別するための値をinput hiddenで用意したとしましょう。これをノードの直接変更で別のポケモンが指定されてしまえば、本来覚えるはずのない技を覚えさせることが出来てしまいます。こういったバグを回避するためにも、できるだけPOSTする値にはクラス名や対象を特定するようなものは避けています。

オーダーを使った処理をしていれば、配列自体が変更されることがないため、最低でも選択肢が増えるということはありませんね。

 

様々なケースを想定していますが、場合によっては回避する手段があるかも知れません。此の辺りは見つけ次第対応予定ですので、ぜひ気づいた方はお問い合わせよりご連絡ください。

 

まとめ

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

今回のPHPポケモンでは「経験値の分配」についてご紹介しました。

WEBアプリケーション開発に興味がある方や、現在プログラミング学習に取り組んでいる方は、ぜひ参考にしてみてくださいね。

 

注目の記事

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

努力値の実装 今回はポケモンのやりこみ要素の一つ、努力値システムを導入します。既に努力値の項目は「ピカチュウで学ぶオブジェクト指向」の段階で実装し、ステータス計算にも判定済みですが、肝心な「努力値を獲得する仕組み」自体は出来ていませんでした。なので、バトルシステムも終盤となったこのタイミングで...

PHPポケモン「レスポンス機能編」メッセージの返却 12
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「レスポンス機能編」メッセージの返却 12

  第12回PHPポケモンは「レスポンス機能編」です。 メッセージやデータのやり取り部分を、よりシステム風に作成していきます。   第1回はコチラ   レスポンス(Response)の実装  今までは結果(メッセージ等)はechoを使って出力していましたが処理が行われたタイミングで出力されてしまうため...

レベルアップ時のステータス表示編 PHPポケモン 48
プログラミング
PHP,PHPポケモン,ポケモン
レベルアップ時のステータス表示編 PHPポケモン 48

ステータスの表示 前回経験値バーのアニメーションとレベルアップ時の動的な変更を実装しましたが、レベルアップ時に表示されるステータスの実装は先送りにしていました。なので今回はそのステータス表示を作成しましょう。   ステータスはメッセージとして返却せずに、小モーダルを起動させるという方法で対応しま...

名刺は時代遅れ!?Googleの名刺検索「ピープルカード」とは
フリーランス
Google,SEO
名刺は時代遅れ!?Googleの名刺検索「ピープルカード」とは

  Googleが2020年8月よりインドでピープルカードの検索機能を開始しました。これがフリーランスや個人事業主、起業家などに対して営業ツールとして大きな影響をもたらすのでは無いかと期待されており、今後ビジネスにおける繋がりが大きく変化していくことも予想されます。   今回は、そんなGoogleの新し...

HPバーアニメーション 後編 フロント側の対応 PHPポケモン 44
プログラミング
PHP,PHPポケモン,ポケモン
HPバーアニメーション 後編 フロント側の対応 PHPポケモン 44

HPバーアニメーション それでは前回に続き、HPバーのアニメーションづくりをしていきましょう。前回、メッセージに合わせてレスポンスを返却するというサーバー側の仕組みを作成しました。なので、今回はそれをフロント側で受け取り、タイミングよくアニメーションで再現します。   フロント側(js)の処理 前回...

Laravelで生成したCookie情報をjQueryで取得する方法【JavaScript】
プログラミング
ajax,api,JavaScript,jQuery,Laravel,PHP
Laravelで生成したCookie情報をjQueryで取得する方法【JavaScript】

  今回はLaravel開発備忘録です。 ajaxでapi認証してviewに記述したhtmlデータを取得するために、cookieを使ったapi_tokenの受け渡し手順をまとめてみました。   Laravelを使った開発をしている人は、ぜひ参考にしてくださいね。     Laravel側の処理   まずはcookieにデータをセットする必要があり...

パーティー実装編 戦闘に参加するポケモン PHPポケモン64
プログラミング
PHP,PHPポケモン,ポケモン
パーティー実装編 戦闘に参加するポケモン PHPポケモン64

先頭のポケモンを選出 前回パーティーのプロパティを準備して、複数(6匹)のポケモンを持ち歩けるようにすることを想定しました。 今回は、そこからバトル画面への連動をさせる部分までを作り込んでいきましょう。   複数のポケモンを所有している場合、戦闘が始まって繰り出されるのは「ひんし状態を除く一番上...

アクセス層とは – 物理的な信号の伝送【第4回 ド素人のためのネットワーク講座】
ネットワーク
TCP/IP,Wi-Fi,アクセス層,無線LAN
アクセス層とは – 物理的な信号の伝送【第4回 ド素人のためのネットワーク講座】

  第4回のド素人のためのネットワーク講座は アクセス層の物理的な役割について です。   実際にデータを送る際にはどのような信号が送られて、どういったことに影響を受けているのかを解説していきます。     信号を伝達する   TCP/IPモデルの第一層(レイヤー1)のアクセス層が担っている役割の...

カテゴリ

SEO対策 イベント デザイン ネットワーク ビジネスモデル フリーランス プログラミング マーケティング ライティング 動画編集 雑記

タグ

5G Adobe AfterEffects AI ajax amazon Animate api artisan atom Automator AWS Bluetooth CSS CVR description EC-CUBE4 ECショップ ESLint Facebook feedly foreach fortify function Google Google AdSense Honeycode htaccess HTML IEEE 802.11ax Illustrator Instagram IoT JavaScript jetstream jQuery jQuery UI keyword LAN Laravel Linux MacBook MAMP meta MLM MySQL NoCode note OS OSI参照モデル Paypal Photoshop PHP phpMyAdmin PHPポケモン PremierePro rss 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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 認証 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力