プログラミング

PHPポケモン「UI(Bootstrap4の導入)編」コード配布・デモ有り 13

PHP PHPポケモン ポケモン
PHPポケモン「UI(Bootstrap4の導入)編」コード配布・デモ有り 13

 

第13回のPHPポケモンは「UI編」ということで、CSSの大人気フレームワークBootstrapさんにお手伝いいただきます。

また、前回実装したレスポンス機能により進化のアクションに一部不具合が出ていたので、このあたりも合わせて修正をしながら進めていきましょう。

 

Bootstrapを導入するにあたり、今までindex.phpに書き込んでいたものを分割するため、新しくResourcesの階層を追加しています。

 

 最後にはコード配布デモページを用意しているので、ぜひ最後まで読んでからご活用ください。

  

Bootstrapの導入

 まずは見た目から見直しをしていきます。ただ、整えるためにCSSを打ち込んでいけばそれだけでかなりの量になってしまうため、前述したとおり今回は大人気CSSのフレームワーク「Bootstrap」のお力を借ります。

とはいっても、線を引いたり余白を整えたりフォームのデザインをお借りするなど、単純なクラスだけしか利用しない(予定)なので、Bootstrapを学習目的の方はその旨ご理解ください

 

出力ファイル(/index.php
# head内に記述
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">

  

ステータス詳細の常時表示化

ステータスや詳細を表示するのに、今まではアクションで選択していましたが、これらは常時確認できるに越したことはありません。なので、もし既にポケモンを選択済みであれば出力するようにしましょう。

 

出力ファイル(/index.php
<?php if(isset($controller->pokemon)): ?>
    <section>
        <div class="row">
            <div class="col-12 col-sm-6">
                <?php foreach($controller->pokemon->getDetails() as $key => $val): ?>
                    <dl class="row">
                        <dt class="col-4"><?=$key?></dt>
                        <?php if(is_array($val)) $val = implode(',', $val); ?>
                        <dd class="col-8"><?=$val?></dd>
                    </dl>
                <?php endforeach; ?>
            </div>
            <div class="col-12 col-sm-6">
                <?php foreach($controller->pokemon->getStats() as $key => $val): ?>
                    <dl class="row">
                        <dt class="col-4"><?=$key?></dt>
                        <dd class="col-8"><?=$val?></dd>
                    </dl>
                <?php endforeach; ?>
            </div>
        </div>
    </section>
<?php endif; ?>

 

技一覧の出力には、再度implodeを使用しています。出力結果は以下のとおりです。

 

 

 

これで選択しているポケモンの詳細がひと目で分かるようになりました。

 

 

フォームの分割 

次にフォーム部分を見直ししていきます。前回は配列として項目やメソッドを用意しましたが、増えていけば自由度が制限されてしまい、それこそ保守性が悪くなってしまうため。ファイルを分割して管理していきます。 

さらに、今までは全データをポストしていましたが、メソッドごとにフォームを用意することで解決ができるということが判明したので、こちらも合わせて実装していきます。

 

ポケモンの選択フォーム(/Resources/Parcials/Forms/select_pokemon.php
<form action=" <?=$action_path?>" method="post">
    <p>ポケモンを選択してください</p>
    <div class="input-group">
        <select class="form-control" id="select_pokemon" name="pokemon">
            <option>--選択してください--</option>
            <?php foreach($controller->getPokemonList() as $class => $pokemon): ?>
                <option value="<?=$class?>"><?=$pokemon?></option>
            <?php endforeach; ?>
        </select>
        <div class="input-group-append">
            <button type="submit" class="btn btn-primary">ゲット</button>
        </div>
    </div>
</form>

 

ニックネームの変更フォーム(/Resources/Parcials/Forms/change_nickname.php
<form action="<?=$action_path?>" method="post">
    <input type="hidden" name="action" value="setNickname">
    <div class="input-group mb-3">
      <input type="text" class="form-control" placeholder="最大5文字" name="param" aria-describedby="submit-setNickname">
      <div class="input-group-append">
          <input class="btn btn-primary" type="submit" id="submit-setNickname" value="ニックネームを変更">
      </div>
    </div>
</form>

 

経験値の取得フォーム(/Resources/Parcials/Forms/add_exp.php
<form action="<?=$action_path?>" method="post">
    <input type="hidden" name="action" value="setExp">
    <div class="input-group mb-3">
      <input type="number" class="form-control" min="1" name="param" aria-describedby="submit-setExp">
      <div class="input-group-append">
          <input class="btn btn-primary" type="submit" id="submit-setExp" value="経験値を取得">
      </div>
    </div>
</form>

 

リセットフォーム(/Resources/Parcials/Forms/reset.php
<form action="<?=$action_path?>" method="post">
    <input type="hidden" name="action" value="reset">
    <input class="btn btn-danger" type="submit" value="リセット">
</form>

 

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

 

それぞれのフォームのアクションパス($action_path)はindex.phpで指定しています。現在はフォームの使いまわしをしていませんが、後々使い回す際に役立つために変数で管理しています。

 

それぞれにフォームを割り当てることで、パラメーターの指定が楽になりましたね。

  1. アクションが選択不要になったため、hiddenで隠しパラメーターとして用意
  2. パラメーターのメソッド判定が不要になったため、nameparamに変更

 

この仕様に合わせてコントローラー側も修正しましょう。

 

コントローラー(/Classes/Controller.php
/**
* @return void
*/
public function __construct($post, $session)
{
    if(get_parent_class($session['pokemon'] ?? null) === 'Pokemon'){
        // Pokemonのインスタンスに溜まったメッセージとレスポンスデータを初期化
        $session['pokemon']->resetMessage();
        $session['pokemon']->resetResponse();
    }
    if(isset($post['pokemon'])){
        // ポケモンをゲットした
        $this->checkPokemon($post['pokemon']);
    }
    if(isset($post['action'])){
        // アクションを選択した
        $this->pokemon = $session['pokemon'] ?? null; # 更新時エラー回避用にnullをセット
        // アクションメソッドの実行
        $this->action($post['action'], $post['param'] ?? null);
    }
}
 
--省略
 
/**
* アクション
*
* @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;
        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');
    }
}

 

パラメーター($param)の判別が無くなった分、簡易化することができました。表示を確認してみましょう。

 

 

  

Bootstrapのおかげで大分使いやすくなりましたUIの重要性を改めて感じます。

 

進化アクションの見直し 

次に進化アクションを一部見直したいと思います。前回の仕様で行くと「進化してもメッセージが引き継がれない」という問題がありました。なので、進化後にメッセージを引き継ぐ処理を追加します。

 

ポケモンクラス(/Classes/Pokemon.php
/**
* インスタンス作成時に実行される処理
*
* @param object|null
* @return void
*/
public function __construct($before=null)
{
    // 進化前のポケモンと一致しているかチェック
    if(is_a($before, $this->before_class ?? null)){
        // 進化した際の処理
        $this->takeOverAbility($before);
        // メッセージの引き継ぎ
        $this->setMessage($before->getMessages());
        $this->setMessage($this->name.'に進化した', 'success');
        $this->checkMove();
    }else{
        // 捕まえた際の処理
        $this->setLevel();
        $this->setDefaultExp();
        $this->setDefaultMove();
        $this->setIv();
        $this->setMessage($this->name.'をゲットした', 'success');
    }
}

 

進化メッセージの前に、進化前($before)からのメッセージを引き継ぎさせます。これで進化後にメッセージが消えてしまうという不具合を解消することができました。

 

進化前プロパティの設定

各ポケモンに割り当てていた 進化メソッド(evolve)についても少し見直しをしましょう。

evolveというメソッドはポケモン共通項目です。もちろん進化条件などは様々ですが、現状では特に分けておく必要性もないためポケモンクラスへ移動させましょう。そしてそのためには、進化先を判別できる必要があるので、各ポケモンに進化先のプロパティを用意します。リザードのクラスを例に見てみましょう。

 

リザードのクラス(/Classes/Pokemon/Lezardo.php)
/**
* 進化前(クラス名)
* @var string
*/
protected $before_class = 'Hitokage';
 
/**
* 進化後(クラス名)
* @var string
*/
protected $after_class = 'Lizardon';

※前回までは進化前のクラス用プロパティをchild_classとしていましたが、そうなると進化先のクラス用プロパティを「parent_class」とする必要があり、意味が異なってしまうため、before_classに名称変更しました

 

最終進化のリザードンやライチュウなどは不要のプロパティです。では、ポケモンクラスに移動したevolveメソッドを見直していきましょう。

 

ポケモンクラス(/Classes/Pokemon.php
/**
* 進化
*
* @return Classes\Pokemon\$after_class
*/
protected function evolve()
{
    if(class_exists($this->after_class ?? null)){
        $pokemon = new $this->after_class($this);
        // 進化後のインスタンスを返却
        return $pokemon;
    }else{
        $this->setMessage('このポケモンは進化できません', 'error');
    }
}

 

進化前の判別と同じように、class_existsを使って正しい進化先かどうかを判定しています。これで各ポケモンに設定しているevolveメソッドは不要になりましたので、削除しておきましょう。

 

コードの配布

 出力用ファイルを階層分けした関係で大幅な変更が出ているので、第13回終了時点でのコードをGitHubより配布します。ぜひご活用ください。

 

デモページ

UIの変更により大分遊びやすくなったので、興味ある人はぜひデモページで遊んでみてください。

デモページ

 

まとめ

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

今回のPHPポケモンは「UIの変更(Bootstrapの導入)」についてご紹介しました。

ゲームは見た目が重要です。PHPではバックエンドの処理がメインとなるため、どうしてもJavascriptCSSの力に頼ることが多くなるでしょう。これらは状況に合わせて活用しながら、あくまでPHPでの処理をメインとして紹介していく予定です。

Webプログラミングに興味がある方は、ぜひ参考にしてくださいね。

 

注目の記事

PHPポケモン「行動順判定+敵ポケモン攻撃編」25
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「行動順判定+敵ポケモン攻撃編」25

行動順の判定 ポケモンの行動順は以下の通りです。 技の優先度 すばやさの実数値(補正有り) 同速の場合は50%の乱数   この順番で比較を行い、先行後攻を決めます。ただし、これは両者ともに攻撃を選択した場合のみです。アイテムの使用や交代は技よりも優先されますし(※一部技を除く)、にげる...

パーティー実装編 トレーナーの作成 PHPポケモン 63
プログラミング
PHP,PHPポケモン,ポケモン
パーティー実装編 トレーナーの作成 PHPポケモン 63

パーティーとは ポケモンでは、ゲーム・アニメ共に最大6匹のパートナーポケモンと旅をすることができます。7匹以上は持ち歩くことができず、ボックスに転送されてしまうという仕組みです。そして、その6匹のパートナーポケモンの構成をパーティーと呼んでいます。 現在のPHPポケモンでは1匹のポケモンしか管理で...

HPバー色変更編(アニメーション) PHPポケモン53
プログラミング
PHP,PHPポケモン,ポケモン
HPバー色変更編(アニメーション) PHPポケモン53

HPバーの色変更 残りHPの割合に合わせて色クラスをセットしていましたが、ダメージを受けた際の判定処理(動的は変更)が未実装でしたので、今回はコチラを対応します。   残数(割合)の判定 HPの色判定は、HTMLの描画時とJSによるHP変動時に行います。animateメソッド前や後に行うと変更のズレが生じるため、a...

仕事用PCは2年で買い替えろ!その理由とは?
フリーランス
MacBook
仕事用PCは2年で買い替えろ!その理由とは?

  「あなたはパソコンをどのタイミングで買い替えますか?」   私は先日、2015年モデルのMacbookPro15インチから最新モデルのMacbookPro13インチに買い替えました。その理由は、メモリが32GBになったことや、15インチが持ち運びという点で見れば向いていないと判断したということ、そこそこの年数が経...

ポケモンプロパティ編(全国図鑑No・捕捉率・重さ) PHPポケモン 77
プログラミング
PHP,PHPポケモン,ポケモン
ポケモンプロパティ編(全国図鑑No・捕捉率・重さ) PHPポケモン 77

PHPポケモン記事も記念すべき第77回を迎えることができ、これもひとえに皆様のお力があってのことです。いろんな方のご協力もあり(ドット絵とかドット絵とかドット絵とか)見た目はかなりゲームらしくなってきました。 しかし、肝心のゲーム要素が本家と比べればまだまだ機能も少なく未実装の項目も多いので、これ...

ピカチュウから学ぶオブジェクト指向 〜クラス継承編〜 2
プログラミング
PHP,PHPポケモン,オブジェクト指向,ポケモン
ピカチュウから学ぶオブジェクト指向 〜クラス継承編〜 2

  ピカチュウから学ぶオブジェクト指向の第2弾はオブジェクトの継承についてです。 前回作成したピカチュウクラスを使用するので、もし基礎的な内容を学習したい人は、以下の記事を参考にしてください。   オブジェクトの継承が理解できれば、複雑で規模の大きなシステムを構築することができるようになり...

PHPポケモン「UI(Bootstrap4の導入)編」コード配布・デモ有り 13
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「UI(Bootstrap4の導入)編」コード配布・デモ有り 13

  第13回のPHPポケモンは「UI編」ということで、CSSの大人気フレームワークBootstrapさんにお手伝いいただきます。 また、前回実装したレスポンス機能により進化のアクションに一部不具合が出ていたので、このあたりも合わせて修正をしながら進めていきましょう。   Bootstrapを導入するにあたり、今までin...

ポケモン図鑑編 PHPポケモン 88
プログラミング
PHP,PHPポケモン,ポケモン
ポケモン図鑑編 PHPポケモン 88

ポケモン図鑑とは ポケモンに出会ったり、仲間にしたりすると、ポケモン図鑑のデータがどんどんと埋まっていきます。PHPポケモンでもこの仕組みを実現させるために、ポケモン図鑑を作成していきましょう。   クラスによる管理 ポケモン図鑑はクラス管理をしていきます。プレイヤー1人に対して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 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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 認証 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力