プログラミング

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

 

注目の記事

売れるECサイトになるために必要な3つの戦略
マーケティング
ECショップ,コンサルティング
売れるECサイトになるために必要な3つの戦略

  ECサイトで全く売れない・・・   ネットショップのオープンが手軽で安価になり、クレジット決済も主流の今ECサイトを立ち上げるお店も増えてきました。 しかし期待感とは裏腹に、思ったような売上が出なかったり、お客さんが1人も獲得できていないケースも少なくありません。   今回はそういった「...

ゆびをふる編 PHPポケモン 69
プログラミング
PHP,PHPポケモン,ポケモン
ゆびをふる編 PHPポケモン 69

ゆびをふるとは 今回PHPポケモンで実装する技は「ゆびをふる」です。  ゆびをふる(ポケモンwiki) https://wiki.ポケモン.com/wiki/ゆびをふる   「ゆびをふる大会」というゆびをふるのみを使った大会なども開催されているということもあり、ポケモンの技の中でも初代から長く愛されてきた1つです。で...

英語できたらブログで稼げる 【ネオコピペ】
ライティング
ブログ,翻訳,英語
英語できたらブログで稼げる 【ネオコピペ】

  2010年に楽天が社内公用語の英語化を宣言したのは、多くの人が耳にしたことがあるでしょう。 私からすると、「英語ができることは強み」だという考えから、「これからは英語ができないと行きていけないのでは?」と考えを変えさせられるような、そんな出来事でした。   多言語できるデメリットを見つけるのは難...

独立してから心がけていること【社会人時代と比較して】
フリーランス
フリーランス,独立
独立してから心がけていること【社会人時代と比較して】

  今回は自分が独立してから心がけていることの中から、ある程度上手くいっていることや、オススメできるようなことを簡単に感想付きでまとめてみました。 社会人時代と比較しながらの内容なので、これからフリーランスで生きていこうと思っている人や、社会人という生活にストレスを感じている人は是非参考に...

千利休から学ぶビジネスモデルの作り方3ステップ!守破離とは
ビジネスモデル
千利休から学ぶビジネスモデルの作り方3ステップ!守破離とは

  千利休の利休道歌に以下のような記述があります。 規矩作法 守り尽くして破るとも離るるとても本を忘るな    これは武道や芸道など学びの基礎として考えられ、創造過程のベースとして用いられてきました。これはビジネスモデルを作り上げるという観点から見ても非常に重要かつ、失敗する多くの人が疎...

PHPポケモン「わざ編〜チャージ技の実装〜」34
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「わざ編〜チャージ技の実装〜」34

チャージ技とは ポケモンの技は数多く存在していて、その中でも特別な処理が必要なものがいくつかあります。その1つが「チャージ技」です。 ※チャージ技とはポケモン上で用いられている用語ではありません   現在実装している初代御三家+ピカチュウの初代レベルアップ技の中では以下の2つがあります。 ロ...

【配列とは】初心者が最短でPHPを使えるようになるための実践的な学び方
プログラミング
foreach,PHP,配列
【配列とは】初心者が最短でPHPを使えるようになるための実践的な学び方

  初心者の方、今からプログラミングを始める方、HTMLとCSSの領域から抜け出せない人たちを対象にした、PHPをできるだけ使えるようになるための方法を紹介するコーナー。 栄えある第二回は【配列編】です。   第一回を飛ばしてこのページへに来てしまい「変数って何?」というレベルの人は、第一回の【変数編...

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

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

カテゴリ

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

タグ

5G Adobe AfterEffects AI ajax amazon Animate api artisan atom Automator AWS Bluetooth CSS CVR description EC-CUBE4 ECショップ ESLint Facebook feedly foreach function Google Google AdSense Honeycode htaccess HTML IEEE 802.11ax Illustrator Instagram IoT JavaScript 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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力