Warning: session_save_path(): Cannot change save path when headers already sent in /home/yqual/s-yqual.com/public_html/s-yqual/public/yqual/wp-content/themes/yqual/session.php on line 2

Warning: session_start(): Cannot start session when headers already sent in /home/yqual/s-yqual.com/public_html/s-yqual/public/yqual/wp-content/themes/yqual/session.php on line 3

Warning: session_regenerate_id(): Cannot regenerate session id - session is not active in /home/yqual/s-yqual.com/public_html/s-yqual/public/yqual/wp-content/themes/yqual/session.php on line 5
プログラミング

PHPポケモン「野生ポケモン遭遇編」18

PHP PHPポケモン ポケモン
PHPポケモン「野生ポケモン遭遇編」18

 

PHPポケモンが第18回にしていよいよバトルの第一歩、野生ポケモンとの遭遇編に突入です。

新しいコントローラーの作成と、バトル画面の作成、そしてポケモンデータの受け渡しなどを中心にご紹介します。

 

バトル画面の実装

 ポケモンのゲームでも、野生ポケモンが現れるとバトル画面へ移管します。今回も同画面のまま制御していくのは流石に大変になってきたので、バトル用の画面を新しく作成します。

 

バトル画面(/battle.php
<?php
 
require_once(__DIR__.'/Classes/Controller/BattleController.php');
require_once(__DIR__.'/Resources/Lang/Translation.php');

session_start();
$controller = new BattleController();
?>
<!DOCTYPE html>
<html lang="jp" dir="ltr">
<head>
    <meta charset="utf-8">
    <title>PHPポケモン-バトル-</title>
    <meta name="robots" content="noindex, nofollow" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
    <link rel="stylesheet" href="Resources/Assets/css/style.css">
</head>
<body>
    <header>
        <div class="container">
            <section>
                <div class="row">
                    <div class="col-12">
                        <h1>PHPポケモン-バトル-</h1>
                    </div>
                </div>
            </section>
        </div>
    </header>
    <main>
        <div class="container">
           
        </div>
    </main>
</body>
</html>

 

バトルアクションの追加

 まずはバトル画面へ移管するためのアクションを作成しましょう。

 

出力用ファイル(/index.php
<?php
 
require_once(__DIR__.'/Classes/Controller.php');
require_once(__DIR__.'/Resources/Lang/Translation.php');
 
session_start();
 
$controller = new Controller();
$action_path = '/';
$battle_path = '/battle.php';
 
?>
--省略
 
<div class="col-12 col-sm-6 mb-5">
    <h2 class="mb-3">メソッドの実行</h2>
    <?php if(is_object($controller->pokemon ?? null)): ?>
        <?php $_SESSION['pokemon'] = $controller->pokemon->export(); # ポケモンの情報をセッションに格納 ?>
        <?php include('Resources/Partials/Forms/change_nickname.php'); # ニックネームの変更?>
        <?php include('Resources/Partials/Forms/add_exp.php'); # 経験値の取得 ?>
        <?php include('Resources/Partials/Forms/battle.php'); # バトル ?>
        <?php include('Resources/Partials/Forms/reset.php'); # リセット ?>
    <?php else: ?>
        <?php include('Resources/Partials/Forms/select_pokemon.php'); ?>
    <?php endif; ?>
</div>

 

バトルフォーム(/Resources/Partials/Forms/battle.php
<form action="<?=$battle_path?>" method="post">
    <div class="input-group mb-3">
        <input class="btn btn-success" type="submit" value="バトル">
    </div>
</form>

 

内容は至って簡単です。新しくフォームを作成し、そのアクション(action)にバトル画面のパスを指定してsubmitしています。

 

 

コントローラーの作成

 バトル用画面でも記述していますが、バトル用のコントローラー(BattleController)も合わせて作成します。

 

バトル用コントローラー(/Classes/Controller/ BattleController.php
<?php

require_once(__DIR__.'/../AutoLoader.php');
require_once(__DIR__.'/../../Traits/ResponseTrait.php');
 
// コントローラー
class BattleController
{
    use ResponseTrait;
 
    /**
    * 敵ポケモン格納用
    * @var object
    */
    public $enemy;
 
    /**
    * 自ポケモン格納用
    * @var object
    */
    public $pokemon;
 
    /**
    * @return void
    */
    public function __construct()
    {
        $post = $_POST;
        $session = $_SESSION;
        // オートローダーの起動
        new AutoLoader();
        // 自ポケモンの格納
        $this->myPokemon($session['pokemon']);
        // 敵ポケモンの格納
        if(isset($session['enemy'])){
            $this->enemyPokemon($session['enemy']);
        }else{
            $this->enemyPokemon();
        }
    }
 
    /**
    * 自ポケモンの格納
    *
    * @param array $pokemon
    * @return void
    */
    private function myPokemon($pokemon)
    {
        $this->pokemon = new $pokemon['class_name']($pokemon);
    }
 
    /**
    * 敵ポケモンの格納
    *
    * @param array|null $pokemon
    * @return void
    */
    private function enemyPokemon($pokemon=null)
    {
        if(is_null($pokemon)){
            $this->enemy = new Fushigidane();
            $this->setMessage('野生の'.$this->enemy->getName().'が現れた!');
        }else{
            $this->enemy = new $pokemon['class_name']($pokemon);
        }
    }
 
}

 ※今後は、コントローラーも親クラスを継承する仕様に変更予定です

 

まずはプロパティから見ていきましょう。

/**
* 敵ポケモン格納用
* @var object
*/
public $enemy;
 
/**
* 自ポケモン格納用
* @var object
*/
public $pokemon;

 

自ポケモンの格納用には今までと同様にpokemonのプロパティに格納します。次に相手(野生ポケモン)用の格納プロパティとして、enemyを用意します。前回までは1匹のポケモンをやり取りする形式をとっていましたが、今回からは敵を含めた2匹分をやりとりします。ですが、引き継ぎ処理等は基本的に同じなので、そこまで複雑ではありません。

 

次にコンストラクタを見てみましょう。

/**
* @return void
*/
public function __construct()
{
    $post = $_POST;
    $session = $_SESSION;
    // オートローダーの起動
    new AutoLoader();
    // 自ポケモンの格納
    $this->myPokemon($session['pokemon']);
    // 敵ポケモンの格納
    if(isset($session['enemy'])){
        $this->enemyPokemon($session['enemy']);
    }else{
        $this->enemyPokemon();
    }
}

 

オートローダーはバトルでも活用するので、初めにインスタンス化しておきます。

次にmyPokemonというメソッドを使って前画面から引き継いだ自ポケモンのデータをプロパティへ格納します。敵ポケモンについては、開始時には新規作成2ターン名以降では前回画面から引き継ぐ必要があります。

/**
* 自ポケモンの格納
*
* @param array $pokemon
* @return void
*/
private function myPokemon($pokemon)
{
    $this->pokemon = new $pokemon['class_name']($pokemon);
}

 

myPokemonのメソッドでは、引き継ぎのインスタンスを作成しています。

 次に敵ポケモン格納用メソッド(enemyPokemon)についてです。

/**
* 敵ポケモンの格納
*
* @param array|null $pokemon
* @return void
*/
private function enemyPokemon($pokemon=null)
{
    if(is_null($pokemon)){
        $this->enemy = new Fushigidane();
        $this->setMessage('野生の'.$this->enemy->getName().'が現れた!');
    }else{
        $this->enemy = new $pokemon['class_name']($pokemon);
    }
}

 

引数指定がされていなければ、新しいインスタンスを作成します。今回はランダムではなく、フシギダネが野生で出てくるようにクラス名を指定しました。

ポケモンでは、ターンが進んでいくにつれて個体値が変更になることはありません。なので、前画面から敵のデータも引き継がれていれば、自ポケモン同様に引数をいれてインスタンス化をしています。

 

アクションの作成

 次にバトルアクションを作成します。初代ポケモンのバトルシステムでは以下の4アクションがあるので、それを一つずつに再現していきましょう。

  • たたかう
  • どうぐ
  • ポケモン
  • にげる

  

にげる

 今回は最も簡単なアクション(にげる)を作成します。にげるというアクションは、バトルから離脱することが目的なので、前の画面(index.php)へ移管させるという処理にします。本来、100%逃げられるということはありませんが、バトル要素が実装されていない現状、その判定は今回無視しておきます。

 

バトル画面(/battle.php
<section>
    <div class="row">
        <div class="col-12 col-sm-6 mb-5">
            <h2 class="mb-3">メソッドの実行</h2>
            <?php $_SESSION['pokemon'] = $controller->pokemon->export(); # 自ポケモンの情報をセッションに格納 ?>
            <?php $_SESSION['enemy'] = $controller->enemy->export(); # 敵ポケモンの情報をセッションに格納 ?>
            <?php # 覚えている技 ?>
            <table class="table table-bordered table-hover mb-3">
                <thead class="thead-light">
                    <tr>
                        <th scope="col">使える技</th>
                        <th scope="col">タイプ</th>
                        <th scope="col">PP</th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach($controller->pokemon->getMove() as $move): ?>
                        <tr>
                            <th scope="row" class="w-50"><?=$move->getName()?></th>
                            <td><?=$move->getType()->getName()?></td>
                            <td><?=$move->getPp()?>/<?=$move->getPp()?></td>
                        </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>
            <form action="/" method="post">
                <div class="input-group mb-3">
                    <input type="hidden" name="action" value="retreat">
                    <input class="btn btn-danger" type="submit" value="逃げる">
                </div>
            </form>
        </div>
        <div class="col-12 col-sm-6 mb-5">
            <h2 class="mb-3">実行結果</h2>
            <div class="result-box border p-3 mb-3">
                <?php foreach($controller->getMessages() as list($msg, $status)): ?>
                    <?php if($status == 'error') $class = 'text-danger'; ?>
                    <?php if($status == 'success') $class = 'text-success'; ?>
                    <p class="<?=$class ?? ''?>"><?=$msg?></p>
                <?php endforeach; ?>
            </div>
        </div>
    </div>
</section>

 

技は現状選択できませんが、自ポケモンが正常に引き継がれているかを確認するために用意しています。

逃げるアクションはリセットと同様の形式で、actionキーのhidden要素に対してにげる(retreat)をセットして送るだけのフォームを用意しておきます。フォームのactionについてですが、にげるは前の画面(index.php)へ移管するためのものなので、今回はルートを指定しています。

※もしにげるの判定を実装する場合は、一度battle.phpに対してリクエストを送り、判定の結果成功であればindex.phpへ返却するという処理が必要になります。

 

それでは、にげるのアクションが選択されたときの判定を、indexのコントローラー(Controller.php)に追加しましょう。

 

コントローラー(/Classes/Controller.php
/**
* アクション
*
* @param string $action(method_name)
* @param mixed $param
* @return void
*/
private function action($action, $param)
{
    // リセットの処理
    if($action === 'reset' || is_null($this->pokemon)){
        // 初期化
        $this->pokemon = null;
        $_POST = [];
        $_SESSION = [];
        return;
    }
    // にげるの処理
    if($action === 'retreat'){
        $this->setMessage('逃げ切れた', 'success');
        unset($_SESSION['enemy']);
        return;
    }
    // 呼び出せるメソッドか判別
    if(is_callable([$this->pokemon, $action])){
        // メソッド実行結果を$resultに格納
        $result = $this->pokemon
        ->$action($param);
        switch ($action) {
            // 経験値の取得
            case 'setExp':
            $this->pokemon = $result;
            break;
        }
        // Pokemonクラスに溜まったメッセージを取得
        $this->setMessage($this->pokemon->getMessages());
    }else{
        $this->setMessage('このアクションは使用できません', 'error');
    }
}

 

処理自体は単純です。retreatのアクションが起こった際は別処理で、メッセージをセットしてからセッションに溜まったenemyをunset(削除)しています。これで、自ポケモンは引き継がれた状態でバトルから抜け出すことができます。

 

以下、敵ポケモンの表示を追加したバトル画面の最終コードです。

 

バトル画面(/battle.php
<?php
 
require_once(__DIR__.'/Classes/Controller/BattleController.php');
require_once(__DIR__.'/Resources/Lang/Translation.php');

session_start();
 
$controller = new BattleController();

?>
<!DOCTYPE html>
<html lang="jp" dir="ltr">
<head>
    <meta charset="utf-8">
    <title>PHPポケモン-バトル-</title>
    <meta name="robots" content="noindex, nofollow" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
    <link rel="stylesheet" href="Resources/Assets/css/style.css">
</head>
<body>
    <header>
        <div class="container">
            <section>
                <div class="row">
                    <div class="col-12">
                        <h1>PHPポケモン-バトル-</h1>
                    </div>
                </div>
            </section>
        </div>
    </header>
    <main>
        <div class="container">
            <section>
                <div class="row">
                    <?php # 敵ポケモン詳細 ?>
                    <div class="col-6">
                        <p><?=$controller->enemy->getName()?> Lv:<?=$controller->enemy->getLevel()?></p>
                    </div>
                    <div class="col-6">
                        <img src="/Resources/Assets/img/pokemon/dots/<?=get_class($controller->enemy)?>.gif" alt="<?=$controller->enemy->getName()?>">
                    </div>
                </div>
            </section>
            <section>
                <div class="row">
                    <div class="col-12 col-sm-6 mb-5">
                        <h2 class="mb-3">メソッドの実行</h2>
                        <?php $_SESSION['pokemon'] = $controller->pokemon->export(); # 自ポケモンの情報をセッションに格納 ?>
                        <?php $_SESSION['enemy'] = $controller->enemy->export(); # 敵ポケモンの情報をセッションに格納 ?>
                        <?php # 覚えている技 ?>
                        <table class="table table-bordered table-hover mb-3">
                            <thead class="thead-light">
                                <tr>
                                    <th scope="col">使える技</th>
                                    <th scope="col">タイプ</th>
                                    <th scope="col">PP</th>
                                </tr>
                            </thead>
                            <tbody>
                                <?php foreach($controller->pokemon->getMove() as $move): ?>
                                    <tr>
                                        <th scope="row" class="w-50"><?=$move->getName()?></th>
                                        <td><?=$move->getType()->getName()?></td>
                                        <td><?=$move->getPp()?>/<?=$move->getPp()?></td>
                                    </tr>
                                <?php endforeach; ?>
                            </tbody>
                        </table>
                        <form action="/" method="post">
                            <div class="input-group mb-3">
                                <input type="hidden" name="action" value="retreat">
                                <input class="btn btn-danger" type="submit" value="逃げる">
                            </div>
                        </form>
                    </div>
                    <div class="col-12 col-sm-6 mb-5">
                        <h2 class="mb-3">実行結果</h2>
                        <div class="result-box border p-3 mb-3">
                            <?php foreach($controller->getMessages() as list($msg, $status)): ?>
                                <?php if($status == 'error') $class = 'text-danger'; ?>
                                <?php if($status == 'success') $class = 'text-success'; ?>
                                <p class="<?=$class ?? ''?>"><?=$msg?></p>
                            <?php endforeach; ?>
                        </div>
                    </div>
                </div>
            </section>
        </div>
    </main>
</body>
</html>

 

 

※複数のポケモンをやり取りすることになったので、画像を追加しました。とはいっても、ドット絵をお借りして表示しているだけです。

 

あとは、にげるボタンを押して、正常に前の画面へ戻ることができれば完了です。

 

 

まとめ

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

今回のPHPポケモンでは「野生ポケモン遭遇編」をご紹介しました。

画面移管は適切に行えば、その分無駄な判定処理が少なく済みます。ですが、そのためにどのようにデータを渡せば良いかが重要になります。

 

現在プログラミング学習に取り組んでいる方は、ぜひ参考にしてくださいね。

 

注目の記事

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

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

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

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

20代の独立が成功のカギ【学生→フリーランス・起業は危険です】
フリーランス
フリーランス,独立,起業
20代の独立が成功のカギ【学生→フリーランス・起業は危険です】

  終身雇用のほとんどが崩壊している今、学生の頃から独立や起業を考えている人は多いですが、安易な決断は危険です。 独立するには早すぎるのも良いとは言えず、また遅すぎることもそれなりにリスクです。 SNSやメディアでも学生起業などが騒がれていますが、それに影響されてしまうのはかなり危険なことです...

フリーランス向けの営業コミュ力向上マニュアル
フリーランス
コミュニケーション能力,フリーランス,営業
フリーランス向けの営業コミュ力向上マニュアル

  せっかくの技術があっても、フリーランスで生計が立てられない 生計は立てられていても、技術レベルに比べて収入が見合っていない   そういった人は非常に多いです。 共通しているのは、営業力の弱さです。   営業は仕事に置いては基本であり究極です。 しかし、フリーランスになる方の多くは技術...

ゲームバランス調整編 DateTimeクラスの活用 PHPポケモン 101
プログラミング
PHP,PHPポケモン,ポケモン
ゲームバランス調整編 DateTimeクラスの活用 PHPポケモン 101

ゲームバランスの調整 まだまだ開発途中のPHPポケモンはゲームバランスの調整がほとんどされていません。現段階では機能も揃っていない関係上、完全なゲームバランスを求めて行くことにはあまり意味がありませんが、今後調整するための役割として機能自体は作成しておこうというのが今回の目的です。   トレーナ...

ブログ収益化の道!挫折ポイントの回避方法を徹底解説【アドセンス合格は通過点、意外な収益ポイントとは】
ライティング
Google AdSense,ブログ
ブログ収益化の道!挫折ポイントの回避方法を徹底解説【アドセンス合格は通過点、意外な収益ポイントとは】

  ノマドワークや副業としてブログ単体で稼げるようになりたいと考えている人は多いですが、その大半は挫折してしまいます。 アドセンスの合格までに辿りつけなかったり、合格したは良いものの思うように伸びずに諦めてしまうというのがほとんどです。 実は、そのアドセンスに対する考え方自体が間違いであり...

ポケモン預かりシステム編 PHPポケモン 85
プログラミング
PHP,PHPポケモン,ポケモン
ポケモン預かりシステム編 PHPポケモン 85

ポケモン預かりシステムとは ポケモンは手持ち(パーティー)に6匹しか入れることができません。そのため、ポケモンを捕まえた際にその上限に達していれば、ボックスへ転送するという仕組みをPHPポケモンでも実装していきます。これが、ポケモン預かりシステムです。 今回は前段階であるボックスの仕様決めをメイン...

PHPポケモン「バトルシステム編 〜バトル終了判定〜」28
プログラミング
JavaScript,jQuery,PHP,PHPポケモン,ポケモン
PHPポケモン「バトルシステム編 〜バトル終了判定〜」28

バトル終了判定 今回はバトル終了判定を実装しましょう。今までは「にげる」による戦闘離脱のみで、ひんし状態でも殴り合うことが出来たので、それを解消するためにも戦闘結果による判定を導入します。   ひんし状態の監視 まずは「ひんし」の監視です。現在は交代ポケモンどちらか一方がひんし状態になれば、そ...

カテゴリ

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