プログラミング

経験値分配編 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アプリケーション開発に興味がある方や、現在プログラミング学習に取り組んでいる方は、ぜひ参考にしてみてくださいね。

 

注目の記事

デザインとブランディングが生み出す本当の価値とは
デザイン
UCC
デザインとブランディングが生み出す本当の価値とは

  商品やHPなど様々なところで価値を提供している「デザイン」ですが、それがもつ本当の意味や価値というものは意外と知られていません。 一般的にはイメージを作る・伝えるということで要求されるものですが、突き詰めた先には人間の深層心理に働きかけるブランディングという要素が潜んでいるのです。   今...

具体的にフリーランスで生きていくには -独立してからの働き方を徹底解説-
フリーランス
フリーランス,独立
具体的にフリーランスで生きていくには -独立してからの働き方を徹底解説-

  安定した仕事に就きたい。。。   多くの人がそう思っていた時代はどんどんと変化して、今やフリーランスでいることの方が安定しているのではないかと言えるような時代です。 そう、もはや会社員でいる人の大半が安定ではなくなってきているのです。 フリーランスでいる人も、根本的に安定という...

get_template_partで引数を渡す方法(WordPress5.5以降)
プログラミング
PHP,WordPress
get_template_partで引数を渡す方法(WordPress5.5以降)

WordPress5.5へのバージョンアップで、大きく機能が追加されました。中には変更に戸惑っている人もいるかも知れませんが、個人的にはエンジニアの要望を大きく取り入れて自由度がアップした印象があります。 今回はその中でも、多くの方が待ち望んでいた「get_template_part」の変更点についてご紹介します。 ge...

定数と静的変数 ピカチュウとイーブイで学ぶオブジェクト指向
プログラミング
PHP,PHPポケモン,イーブイ,オブジェクト指向,ピカチュウ,ポケモン
定数と静的変数 ピカチュウとイーブイで学ぶオブジェクト指向

PHPポケモンも順調に開発が進んでいると思いきや、ふとした気づきが自分の理解力を思い知らせることとなった今日このごろです。 プログラミングは奥が深く、しっかりと段階を追って理解を進めていけば、「これ・・・便利やんけ!」ってなることがかなり多いということがわかります。   それでは、かの有名な黄色い...

動画編集に役立つ基本的な考え方【Adobe AfterEffects】
動画編集
Adobe,AfterEffects,PremierePro,YouTube
動画編集に役立つ基本的な考え方【Adobe AfterEffects】

  YouTubeの人気に合わせて、動画編集の需要も高まってきましたが、その大変さから挫折してしまう人も続出しています。 動画編集は奥が深く、技術的な部分に関してはプロのクリエイターであっても自分がよく使うような一部しか把握していないのが普通であり、調べても該当する情報が出てきにくいということもあ...

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

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

引き継ぎ考慮のメッセージID重複回避編 PHPポケモン 58
プログラミング
PHP,PHPポケモン,ポケモン
引き継ぎ考慮のメッセージID重複回避編 PHPポケモン 58

今回のPHPポケモンでは内部の作り込みをしていきます。見た目への反映は無いので、プレイを楽しみにしている人や、ポケモンが好きで毎日チェックしてくれているような人は、ブラウザをバックしてもらって問題ありません。   それでは、前々回辺りから保留にしていた「メッセージIDに重複回避対策」についてです。 &...

熟練者ほど実践するプログラミングが上達する3つの法則
プログラミング
PHP
熟練者ほど実践するプログラミングが上達する3つの法則

  「なかなかプログラミングが上達しない・・・」 「やったことはあるけど覚えられない」   プログラミングを習得しても、勉強と一緒で使っていなければ忘れてしまいます。また、どんどん上達する人や、長い間プログラミングの技術で生計を立てているような熟練者は、日頃からの取り組み方自体が違ってい...

カテゴリ

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 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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 認証 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力