プログラミング

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プログラミングに興味がある方は、ぜひ参考にしてくださいね。

 

注目の記事

【完全未経験OK】プログラミングの始め方 〜学習方法を解説します!〜
プログラミング
CSS,HTML,JavaScript,MAMP,PHP,XAMPP,フリーランス,プログラミング,独立,起業
【完全未経験OK】プログラミングの始め方 〜学習方法を解説します!〜

  プログラミングって難しい   そういう人は多いですね。しかしそんなことは有りません。 言語という点で比較すれば、英語やフランス語など第二言語を学ぶ方が難しいと言えます。   プログラミングの需要は年々高まり、今や最高潮とも言える域まで来ています。 なぜそこまで需要が高いのか?   ...

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

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

動画にカラオケテロップを入れる編集方法【AfterEffectsで色変わりの文字】
動画編集
Adobe,AfterEffects
動画にカラオケテロップを入れる編集方法【AfterEffectsで色変わりの文字】

  動画に声と同じタイミングでテロップを入れたい カラオケのような文字はどうやっていれればいいの?   一見簡単に見えるものも、いざ導入しようとすればどうやればいいかわからない、そんなこと多いのではないでしょうか? 今回はAdobe AfterEffectsを使った方法をご紹介します。些細な編集が動画のク...

本当に価値のある宣伝方法 〜多くの人が実践している【間違った努力】とは〜
マーケティング
Facebook,note,Twitter,YouTube,集客
本当に価値のある宣伝方法 〜多くの人が実践している【間違った努力】とは〜

  YouTubeやTwitter、Facebookやnoteなど、いろんなサービスを使った集客方法があります。集客という視点ではなく、それ自体に人を集めたいという人も多いでしょう。   フォロワーやチャンネル登録者数を増やすために、多くの人が様々な取り組みをしていますが、その中でもひときわ意味のないことをただ繰り返して...

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

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

わざマシン編 作成 PHPポケモン104
プログラミング
PHP,PHPポケモン,ポケモン
わざマシン編 作成 PHPポケモン104

わざマシンとは ポケモンはレベルアップ以外でも技を習得することができます。それが「わざマシン」というアイテムです。  わざマシン(ポケモンwiki) https://wiki.ポケモン.com/wiki/わざマシン   最新世代では「技レコード」というものが有り、使い切りとなっています。初代ではわざマシン自体も使い...

ダメージ固定技編(ちきゅうなげ・カウンター) PHPポケモン 41
プログラミング
PHP,PHPポケモン,ポケモン
ダメージ固定技編(ちきゅうなげ・カウンター) PHPポケモン 41

ダメージ固定技とは PHPポケモンでも作成したダメージ計算機能ですが、ポケモンの技の中にはそれを必要としない技がいくつかあります。それが「固定ダメージ技」です。 ポケモンwiki(ダメージ固定技) https://wiki.ポケモン.com/wiki/ダメージ固定技 ステータスに依存せず、わざ自体にダメージ量が決...

PHPポケモン「技クラス実装編」14
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「技クラス実装編」14

  前回せっかくBootstrapを使って見た目を整えたにも関わらず、ビューポートの記述が抜けているという凡ミスが発覚したので修正しています。 サーセン。   今回のPHPポケモンでは本格的な技システムを実装していきます。技システムが整えば、皆さん期待のバトルシステムも間近です。セキュリティ面やファイル構成...

カテゴリ

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