プログラミング

フレンドリィショップ編 開店準備 PHPポケモン 75

PHP PHPポケモン ポケモン
フレンドリィショップ編 開店準備 PHPポケモン 75

アイテム(どうぐ)

PHPポケモンもバトル機能が一通り揃ってきたので、新機能として「アイテム」の実装に取り掛かります。

アイテムにも色々ありますが、技やポケモンのクラス同様に、初代で登場したアイテムから順番に取り揃えていきましょう。

 

キズぐすりの実装

ポケモンのどうぐ、一番手は「キズぐすり」です。RPGでは欠かせない回復アイテムの1つで、ポケモンの体力を少量回復させる効果をもっています。

スプレー式の キズぐすり。 ポケモン 1匹の HP 20だけ 回復する。

 

アイテムにも、それぞれに効果や使用タイミングがあるため、ポケモンや技同様にクラスによる管理をしていきましょう。

まずはアイテムの親クラス(Item)を作成します。

 

アイテムクラス(/Classes/Item.php
<?php
 
// どうぐ
abstract class Item
{
 
    /**
    * @return void
    */
    public function __construct()
    {
        //
    }
 
    /**
    * 名称の取得
    * @return string
    */
    public function getName()
    {
        return $this->name;
    }
 
    /**
    * カテゴリの取得
    * @return string
    */
    public function getCategory()
    {
        return $this->category;
    }
 
    /**
    * 説明文の取得
    * @return string
    */
    public function getDescription()
    {
        return $this->description;
    }
 
    /**
    * 最大保有数の取得
    * @return integer|null
    */
    public function getMax()
    {
        return $this->max;
    }
 
    /**
    * 買値の取得
    * @return integer
    */
    public function getBidPrice()
    {
        return $this->bid_price;
    }
 
    /**
    * 売値の取得
    * @return integer
    */
    public function getSellPrice()
    {
        return $this->sell_price;
    }
 
}

 

アイテムに持たせるパラメーターを取得するためのメソッドを、親クラスに持たせています。

次に、キズぐすりのクラスを作成しましょう。

 

キズぐすり(/Classes/Item/Potion.php
<?php
$root_path = __DIR__.'/../..';
require_once($root_path.'/Classes/Item.php');
 
// キズぐすり
class ItemPotion extends Item
{
 
    /**
    * 正式名称
    * @var string
    */
    protected $name = 'キズぐすり';
 
    /**
    * 説明文
    * @var string
    */
    protected $description = 'スプレー式のキズぐすり。ポケモン1匹のHPを20だけ回復する。';
 
    /**
    * カテゴリ
    * @var string::general|health|ball|important|machine
    */
    protected $category = 'health';
 
    /**
    * 最大所有数
    * @var integer
    */
    protected $max = 99;
 
    /**
    * 買値
    * @var integer
    */
    protected $bid_price = 200;
 
    /**
    * 売値
    * @var integer
    */
    protected $sell_price = 100;
 
    /**
    * 対象
    * @var string::pokmeon|player
    */
    protected $target = 'pokemon';
 
    /**
    * 使用できるタイミング
    * @var array
    */
    protected $timing = ['battle', 'home'];
 
    /**
    * 効果
    * @return array
    */
    public function effects($pokemon)
    {
        $before = $pokemon->getRemainingHp();
        if($before < $pokemon->getStats('HP')){
            // HP20回復
            $after = $pokemon->calRemainingHp('add', 20);
            $message = $pokemon->getPrefixName().'のHPが'.($after - $before).'回復した';
        }else{
            // 効果なし
            $message = '使っても効果がないよ';
        }
        // メッセージを返却
        return [
            'message' => $message
        ];
    }
 
}

 

まずカテゴリプロパティ(category)についてです。

初代では、アイテムのカテゴリ分けがされておらず、見にくい状態になっていましたが、第2世代からは「ボール」「わざマシン」「大切なもの」などを分けて格納できるようになりました。PHPポケモンでも見やすさ重視で、初代アイテムで実装する項目をカテゴリ分けしていきます。

 

対象(target)使用できるタイミング(timing)については、必要になる可能性が想定されたので設定しました。 

効果メソッド(effects)は、技と同様に配列でメッセージを返却する仕様にしていますが、こちらもバトルやホーム画面へアイテムを使用する機能を組み込みながら調整予定です。

  

フレンドリィショップ

アイテムを実装しても、手に入れる手段がなければ意味がありません。なので、ダミーで準備していたフレンドリィショップに商品を陳列させていきましょう。

 

商品準備

フレンドリィショップへ陳列させる商品は、そのままHTMLの要素として容易せず、configを活用します。

 

ショップconfig/Config/shop.php
<?php
return [
    'ItemPotion'
];

 

現在はキズぐすりしか用意をできていないため、配列としてキズぐすりのクラスだけを返却しています。

次に、コントローラーでフレンドリィショップ用の配列を作成し、ホーム画面から簡単に呼び出せるようにしましょう。

 

ホームコントローラー用トレイト(/Traits/Controller/HomeControllerTrait.php
<?php
 
/**
* ホームコントローラー用トレイト
*/
trait HomeControllerTrait
{
 
    /**
    * 戦闘に参加するポケモン番号を取得
    *
    * @return integer
    */
    protected function getFightPokemonOrder()
    {
        $orders = array_filter($this->party, function($partner){
            return $partner->getRemainingHp() > 0;
        });
        if(empty($orders)){
            return null;
        }else{
            return array_key_first($orders);
        }
    }
 
    /**
    * ショップ情報の取得
    * @return array
    */
    public function getShop()
    {
        return array_map(function($item){
            return new $item;
        },config('shop'));
    }
 
}

 

array_mapを使って、取得したショップ配列の要素をオブジェクトに変換して返しています。どこからでもインスタンス化できるように、Itemディレクトリをオートローダーの対象にしておきましょう。

 

フレンドリィショップではポケモンセンターと違い、購入や売却などいくつか操作が必要になるため、モーダルとして用意します。

 

フレンドリィショップモーダル(/Resources/Partials/Home/Modals/shop.php)
<!-- Modal -->
<div class="modal fade" id="shop-modal" tabindex="-1" role="dialog" aria-labelledby="shop-modal-title" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="shop-modal-title">フレンドリィショップ</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">×</span>
                </button>
            </div>
            <div class="modal-body">
                <?php # ナビ ?>
                <nav class="nav nav-pills nav-justified btn-group mb-3" id="shop-modal-tab">
                    <a class="btn btn-outline-success nav-item nav-link active" id="shop-modal-buy-tab" data-toggle="tab" href="#shop-modal-buy" role="tab" aria-controls="shop-modal-buy" aria-selected="true" data-type="buy">購入</a>
                    <a class="btn btn-outline-info nav-item nav-link" id="shop-modal-sell-tab" data-toggle="tab" href="#shop-modal-sell" role="tab" aria-controls="shop-modal-sell" aria-selected="true" data-type="sell">売却</a>
                </nav>
                <?php # 購入 ?>
                <div class="tab-content mb-3" id="shop-modal-tab-content">
                    <div class="tab-pane fade show active" id="shop-modal-buy" role="tabpanel" aria-labelledby="shop-modal-buy-tab">
                        <form method="post" data-form="shop">
                            <input type="hidden" name="action" value="shop">
                            <input type="hidden" name="do" value="buy">
                            <div class="mb-3 p-3 bg-light">
                                <div class="input-group">
                                    <select class="custom-select col-8" name="order" data-form="buy">
                                        <option value="" selected>----</option>
                                        <?php foreach($controller->getShop() as $order => $item): ?>
                                            <option value="<?=$order?>" data-price="<?=$item->getBidPrice()?>" data-item="<?=$item->getName()?>">
                                                <?=$item->getName()?>(<?=$item->getBidPrice()?>円)
                                            </option>
                                        <?php endforeach; ?>
                                    </select>
                                    <select class="custom-select col-4" name="count" data-form="buy">
                                        <option value="">----</option>
                                        <?php for($i=1;$i<100;$i++): ?>
                                            <option value="<?=$i?>"><?=$i?> 個</option>
                                        <?php endfor; ?>
                                    </select>
                                </div>
                            </div>
                            <div class="alert alert-success" id="shop-buy-calculator" role="alert">
                                <div class="form-group row">
                                    <label class="col-3 col-form-label">おこづかい</label>
                                    <div class="col-9 text-right">
                                        <p class="form-control-plaintext">
                                            <span class='mr-2'><?=$player->getMoney()?></span>円
                                        </p>
                                    </div>
                                </div>
                                <hr>
                                <div class="form-group row">
                                    <label class="col-3 col-form-label">内訳</label>
                                    <div class="col-3 text-right">
                                        <p class="form-control-plaintext">
                                            <span id="shop-buy-item-name"></span>
                                        </p>
                                    </div>
                                    <div class="col-3 text-right">
                                        <p class="form-control-plaintext">
                                            <span id="shop-buy-item-price"></span>
                                        </p>
                                    </div>
                                    <div class="col-3 text-right">
                                        <p class="form-control-plaintext">
                                            <span id="shop-buy-item-count"></span>
                                        </p>
                                    </div>
                                </div>
                                <hr>
                                <div class="form-group row mb-0">
                                    <label class="col-3 col-form-label">合計</label>
                                    <div class="col-9 text-right">
                                        <p class="form-control-plaintext font-weight-bolder">
                                            <span id="shop-buy-total-price" class="mr-2"></span>
                                        </p>
                                    </div>
                                </div>
                                <p data-alert="buy" class="text-danger text-right mb-0 mt-2" style="display:none;">
                                    おこづかいが足りません
                                </p>
                            </div><!-- aleart -->
                            <button type="submit" class="btn btn-success btn-block" id="shop-buy-submit" disabled>購入</button>
                        </form>
                    </div><!-- buy -->
                    <?php # 売却 ?>
                    <div class="tab-pane fade show" id="shop-modal-sell" role="tabpanel" aria-labelledby="shop-modal-sell-tab">
                        <form method="post" data-form="shop">
                            <input type="hidden" name="action" value="shop">
                            <input type="hidden" name="do" value="sell">
                            <div class="mb-3 p-3 bg-light">
                                売却
                            </div>
                            <div class="alert alert-info" id="shop-sell-calculator" role="alert">
                                <div class="form-group row">
                                    <label class="col-3 col-form-label">おこづかい</label>
                                    <div class="col-9 text-right">
                                        <p class="form-control-plaintext">
                                            <span class='mr-2'><?=$player->getMoney()?></span>円
                                        </p>
                                    </div>
                                </div>
                                <hr>
                                <div class="form-group row">
                                    <label class="col-3 col-form-label">内訳</label>
                                    <div class="col-3 text-right">
                                        <p class="form-control-plaintext">
                                            <span id="shop-sell-item-name"></span>
                                        </p>
                                    </div>
                                    <div class="col-3 text-right">
                                        <p class="form-control-plaintext">
                                            <span id="shop-sell-item-price"></span>
                                        </p>
                                    </div>
                                    <div class="col-3 text-right">
                                        <p class="form-control-plaintext">
                                            <span id="shop-sell-item-count"></span>
                                        </p>
                                    </div>
                                </div>
                                <hr>
                                <div class="form-group row mb-0">
                                    <label class="col-3 col-form-label">合計</label>
                                    <div class="col-9 text-right">
                                        <p class="form-control-plaintext font-weight-bolder">
                                            <span id="shop-sell-total-price" class="mr-2"></span>
                                        </p>
                                    </div>
                                </div>
                            </div><!-- aleart -->
                            <button type="submit" class="btn btn-info btn-block" id="shop-sell-submit" disabled>売却</button>
                        </form>
                    </div><!-- sell -->
                </div>
                <input type="hidden" id="player-remaining-money" value="<?=$player->getMoney()?>">
            </div><!-- Modal body -->
        </div><!-- Modal content -->
    </div><!-- Modal dialog -->
</div><!-- Modal  -->

  

ショップの見た目はPHPポケモンオリジナルのものとなっています。アイテムをテーブルとして準備する場合、それぞれにフォームを用意するか、jQueryを使って選択した値をセットしてsubmitしなければなりません。今回はそれらの手間をひとまとめにできるよう、セレクトボックスを採用しました。

 

ポケモンでは、私達が使っているようなネットショップとは異なり、複数のアイテムを一気に購入することはできません。なので、PHPポケモンでもアイテムは1種類ずつ購入する仕様を採用しました。

 

計算機の作成

ポケモンではアイテムと数を選択すると、確認画面としてその合計金額が表示されます。確認画面を入れる場合、もう1枚モーダルを表示する必要があるので、その手間を省くためにPHPポケモンでは購入画面に計算機の機能を持たせました。

選択したアイテムと個数の値をjQueryで受け取り、計算結果を画面上に出力させます。

 

フレンドリィショップ用JS/Pulibc/Assets/js/Home/shop.js
/*----------------------------------------------------------
// 初期化する関数
----------------------------------------------------------*/
 
// おこづかい
var money = $('#player-remaining-money').val();
 
/**
* フレンドリィショップ
* @function change
* @return void
**/
var shopInit = function(){
    $('form[data-form="shop"] select').on('change', function(){
        // フォームの判別
        var form = $(this).data('form');
        // 必要値の取得
        var order_option = $('[data-form="' + form + '"][name="order"] option:selected')
        var price = order_option.data('price');
        var item = order_option.data('item');
        var count = $('[data-form="' + form + '"][name="count"]').val();
        // アイテムが選択されていなければ、計算機をリセット
        if(!item || !count){
            calculatorReset(form);
            return;
        }
        // 合計金額の算出
        var total = price * count;
        // 計算機に値をセット
        $('#shop-' + form + '-item-name').text(item);
        $('#shop-' + form + '-item-price').text(price + ' 円');
        $('#shop-' + form + '-item-count').text(count + ' 個');
        $('#shop-' + form + '-total-price').text(total + ' 円');
        if(money < total){
            $('#shop-' + form + '-submit').prop('disabled', true);
            $('[data-alert="' + form + '"]').show();
        }else{
            $('#shop-' + form + '-submit').prop('disabled', false);
            $('[data-alert="' + form + '"]').hide();
        }
    });
}
 
/**
* モーダル起動時の初期化
* @function change
* @return void
**/
var showModalInit = function(){
    $('#shop-modal').on('show.bs.modal', function(){
        $.each(['buy', 'sell'], function(index, value){
            formReset(value);
            calculatorReset(value);
        })
    });
}
 
/**
* タブクリック時の初期化
* @function change
* @return void
**/
var shopTabInit = function(){
    $('#shop-modal-tab .nav-link').on('click', function(){
        var form = $(this).data('type');
        formReset(form);
        calculatorReset(form);
    });
}
 
/*----------------------------------------------------------
// 処理内で呼び出す関数
----------------------------------------------------------*/
 
/**
* 計算機の初期化
* @param form:string
* @return void
**/
var calculatorReset = function(form){
    $('#shop-' + form + '-item-name').text('-');
    $('#shop-' + form + '-item-price').text('-');
    $('#shop-' + form + '-item-count').text('-');
    $('#shop-' + form + '-total-price').text('-');
    $('[data-alert="' + form + '"]').hide();
    $('#shop-' + form + '-submit').prop('disabled', true);
}
 
/**
* フォームの初期化
* @param form:string
* @return void
**/
var formReset = function(form){
    $('[data-form="'+ form +'"]').val('');
}
 
/*----------------------------------------------------------
// 初期化
----------------------------------------------------------*/
jQuery(function($){
    shopInit();
    shopTabInit();
    showModalInit();
});

 

セレクトボックスの変更を取得し、金額と個数で合計金額を算出、おこづかいが足りているかを判別しています。

フォームではDOMの直接書き換えを考慮して、アイテムクラスや金額を直接飛ばさず、アイテム番号と必要数のみで判別しています。

 

それでは、ショップ計算機の動きを確認してみましょう。

 

計算機が正常に機能していることが確認できました。これで、フレンドリィショップの開店準備は完了です。

 

まとめ

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

今回のPHPポケモンでは「アイテムの実装」と「フレンドリィショップの開店準備」についてご紹介しました。

プログラミング学習に取り組んでいる方や、興味を持たれている方は、ぜひ参考にしてみてくださいね。

 

注目の記事

フリーランスが打ち合わせで押さえておきたい3つのポイント【収入アップします】
フリーランス
フリーランス,営業
フリーランスが打ち合わせで押さえておきたい3つのポイント【収入アップします】

  フリーランスになれば、デザイナーやプログラマーといった制作をメインとする仕事の人でもクライアントと打ち合わせをしなければいけません。 特に独立や起業前のキャリアとして営業職に縁がなかった人からすれば、打ち合わせが苦手な人は多いはずです。   今回は、そういった営業ベタでやり方が分からない...

連続の技習得編 オブジェクトをセッションへ格納 PHPポケモン57
プログラミング
PHP,PHPポケモン,ポケモン
連続の技習得編 オブジェクトをセッションへ格納 PHPポケモン57

セッション経由でのオブジェクト引き継ぎ 技習得の処理が整ってきたので、ここで連続技習得・連続レベルアップ時にも問題なく動作するように作り込んでいきます。ですが、現状のモーダルをレスポンスやメッセージと同様に、そのまま引き継いだとしてもエラーが発生します。 その原因がセッション経由でのオブジェク...

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

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

SNS拡散力アップ!PHPでOG画像付きリッチURLを自作する方法【Curl → Opengraph】
プログラミング
PHP,WordPress
SNS拡散力アップ!PHPでOG画像付きリッチURLを自作する方法【Curl → Opengraph】

  ブログやHPにサイトのURLをただ貼り付けても、どんなページなのか一目でわからないのでなかなか思うようにアクセスに繋がりません。 ですが、毎回のようにURL先の画像を準備したり、説明文を設定するのも大変ですし、ページタイトルや画像が差し替わってしまうことも考えられます。   今回はそういった手間...

バーアニメーションの不具合対応編 PHPポケモン 54
プログラミング
PHP,PHPポケモン,ポケモン
バーアニメーションの不具合対応編 PHPポケモン 54

最近は細々した対応が多くて「早く次のステップに進めよ!」と思っている方も多いでしょう。 ご意見ごもっともですが、残っている対応が意外にも追加しなければいけない処理が多く苦戦しているのが実情だったりします。そして、そのおかげか試行回数が多くなり見過ごしていた不具合や修正不備がポロポロ出てきていま...

【Laravel】1対1リレーションをわかりやすく解説(hasOne)
プログラミング
Laravel,PHP
【Laravel】1対1リレーションをわかりやすく解説(hasOne)

  Laravelの1対1リレーションのhasOneについて、公式マニュアルでは専用単語ばかりでどうしてもわかりにくいと感じてしまっている方へ向けて、わかりやすく解説しました。 ※例で紹介しているコードについては、一部英語を日本語表記で使用している部分もありますので、コピペで使用する方は必要に応じて置...

バトルステータス可視化編 PHPポケモン 70
プログラミング
PHP,PHPポケモン,ポケモン
バトルステータス可視化編 PHPポケモン 70

バトルステータスの可視化 現在のポケモンでは、バトルステータスの現状を可視化できるようになっており、どれぐらいのランク補正がかかっているか、フィールドがどういう状態になっているかがわかるようになっています。 初代、第2世代等では確認できなかった内容ではありますが、システムとしては便利な要素でも...

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

  ※PHP初心者へ向けた内容となりますので、ある程度HTMLの知識がある方を対象とした内容になります。予めご了承ください。    Webプログラミングを学ぶ方はHTML、そしてCSSを学び、そしてJavascriptや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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力