プログラミング

PHPポケモン「オートロード編(修正版)」17 おまけ:日本語化

PHP PHPポケモン ポケモン
PHPポケモン「オートロード編(修正版)」17 おまけ:日本語化

 

前回実装したオートローダーの使い方が盛大に間違っていたので、今回その間違いの説明をしながら、正しい実装方法をご紹介します。

申し訳ありません。(誠意)

  

オートロードについて(再)

 必要なタイミングで必要なファイルをrequireまたはincludeするあれです。

 

前回spl_autoload_registerの関数を使用した簡易オートローダーを作成したのですが、呼び出していないのに必要なクラスを呼び出してインスタンス化されているという現象がタイプの取得部分で起こっていたため、再度公式(PHP.net)や他の紹介記事を参考にしたところ、この関数は一度登録すれば毎回呼び出す必要が無いということが発覚しました。

※よくみればregisterってなってますからね・・・

 

ということで、前回トレイトで作成したオートローダーはなかったことにしてしっかりと理解した上で作り込んでいきます。

 

オートローダーの作成

 1度実行すれば良いのであれば、トレイトである必要はありません。なのでクラスとして作成します。

 

オートローダー(/Classes/AutoLoader.php
<?php
 
class AutoLoader
{
 
    /**
    * 検索するクラスが格納されているフォルダ
    * @return void
    */
    private $folders = [
        'Move', 'Pokemon', 'Type',
    ];
 
    /**
    * オートローダー
    *
    * @return void
    */
    public function __construct()
    {
        spl_autoload_register([$this, 'autoLoader']);
    }
 
    /**
    * コールバック用メソッド
    *
    * @return void
    */
    private function autoLoader($class_name)
    {
        // クラス名からファイルを検索
        foreach($this->folders as $folder){
            $path = __DIR__ . '/../Classes/'.$folder.'/'.$class_name.'.php';
            if(file_exists($path)){
                // 見つかった場合は読み込み実行
                require $path;
            }
        }
    }
}

 

まず、プロパティに注目しましょう。

/**
* 検索するクラスが格納されているフォルダ
* @return void
*/
private $folders = [
    'Move', 'Pokemon', 'Type',
];

 

技(Move)、ポケモン(Pokemon)、タイプ(Type)のClassesに設置した3フォルダを指定しています。もしクラスが見つからなかった際は、ここから探してくれます。もしアイテムなどが増えた際は、ここに必要フォルダを増やしていきましょう。

 

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

/**
* オートローダー
*
* @return void
*/
public function __construct()
{
    spl_autoload_register([$this, 'autoLoader']);
}

 

spl_autoload_registerは処理の前半に1度だけ呼び出しておけば良いので、オートローダーのクラスをインスタンス化した時点で動くようにしました。中にはメソッドを用意して、インスタンス化→メソッド実行という手順をとっているものもありましたが、今の所一括で出来たほうが良いだろうという判断なのでこの仕様にしています。

もし、セキュリティ面や挙動がおかしくなるなど問題が発生したら、適宜修正していきます。

 

コールバック関数は、前回のように無名関数にせず、可視性がよくなるためにもメソッドへ分けて作成しました。

/**
* コールバック用メソッド
*
* @return void
*/
private function autoLoader($class_name)
{
    // クラス名からファイルを検索
    foreach($this->folders as $folder){
        $path = __DIR__ . '/../Classes/'.$folder.'/'.$class_name.'.php';
        if(file_exists($path)){
            // 見つかった場合は読み込み実行
            require $path;
            break;
        }
    }
}

 

読み込まれていないクラスを呼び出そうとしたタイミングで、spl_autoload_registerは起動して、コールバック関数の第1引数に、そのクラス名が渡されます。以下の例を見てみましょう。 

  1. オートローダーをインスタンス化

    spl_autoload_registerが登録される

  2. ピカチュウのクラスを呼び出そうとする

    ピカチュウのクラスはincludeまたはrequireされていない

  3. spl_autoload_registerが動き、コールバック関数(autoLoader)の第1引数($class_name)にPikachu(ピカチュウのクラス名)が渡される

 

上記の流れになります。

そして、コールバック関数内ではforeachを使ってプロパティに設定したフォルダから順番にピカチュウのクラスを検索させています。

 

これだけです。一度登録していれば、見つからないクラスが呼び出された時点で勝手に探してくれるというのが、前回の説明で漏れていた(というより理解できていなかった)部分です。composerの素晴らしさがわかると同時に、頼り切りだと知らないことがいっぱいだということを改めて教えられました。

namespaceを使用していない関係上、一発で該当フォルダへたどり着くことができないため、無駄な動きは発生していますが、膨大な量ではないので今回は無視します。

 

class_existsの挙動について

次に、class_existsの関数について見ていきましょう。これが今回良くも悪くも気づきをくれました。 

 

第2引数でautoloadをデフォルトでコールするかしないかを指定できます。省略すればtrueになるのでコールしてくれます。

最初は関係ないと思ってスルーしていましたが、オートローダーを実装した途端これが大きな意味を成してきました。

 

技の習得や、進化をする際にclass_existsを何度か使用しています。これは、クラスが不正なものでは無いか(または名称間違いになっていないか)を判別するぐらいで使用していたのですが、オートローダーを導入した関係上、基本的にはクラスは存在しない(読み込まれていない状態)ものをチェックすることになります。その際に、それをオートロードを実行してからチェックするかどうかというのが、class_existsの第2引数の役割です。

通常のclass_existsを使う場合、第2引数にはfalseを指定することが多いです。その理由は、基本的にはクラスは読み込んでいることが前提だからです。しかし、今回のPHPポケモンの現段階で使用しているclass_existsは、基本的に読み込んでいないクラスを探してもらうため、第2引数は省略(true)のままで進めていきます。

 

では、実際に修正箇所を見ていきましょう。

 

コントローラー(/Classes/Controller.php
/**
* @return void
*/
public function __construct($post, $session)
{
    // オートローダーの起動
    new AutoLoader();

 

まず、コントローラーの最初にオートローダーをインスタンス化します。これで、spl_autoload_registerが登録されたことになります。

※AutoLoader.phpはrequireしておいてください

 

インスタンス化トレイト(/Traits/InstanceTrait.php
<?php
 
trait InstanceTrait
{
    /**
    * インスタンス化関数
    * @param string $class_name
    * @return object
    */
    protected function getInstance($class_name)
    {
        // 存在チェックをして読み込み
        if(class_exists($class_name)){
            return new $class_name();
        }
    }
 
}

 

インスタンス化用のトレイトも、前回まではポケモンや技など種類分けをしていましたが、その必要が無くなったので簡潔なものに戻しています。

あとは、インスタンス化したい際に使用すれば、class_existsで勝手にクラスを探して読み込んでくれるという仕様です。

 

ポケモンデータの引き継ぎ

 これでタイプや技に関しては上手く行きましたが、ポケモンクラスで問題が発生しました。

今まではコントローラーで各ポケモンのクラスを読み込んでいたのですが、これをオートローダーに変更したところメソッド等が呼び出せなくなりました。原因を確認したところ、セッション内に以下のようなものが入力されていました。 

__PHP_Incomplete_Class Object

 

そもそも、インスタンスはセッションで渡すべきでは無いそうです。よくよく考えたら、セキュリティの関係からも当たり前と納得です。なので、こちらも修正します。

 

いままでは、ポケモンをインスタンス化する際に「捕まえた」「進化前」だけを判定していました。ですが、前画面から同じポケモンの引き継ぎという判定を追加しなければいけません。必要なデータだけを配列としてセッションに渡し、コントローラーの最初でその引き継ぎデータ(配列)を使って新しくポケモンをインスタンス化します。

 

ではまずポケモンクラスの修正版から見ていきましょう。

 

ポケモンクラス(/Classes/Pokemon.php
<?php

require_once(__DIR__.'/../Traits/ResponseTrait.php');
require_once(__DIR__.'/../Traits/InstanceTrait.php');
require_once(__DIR__.'/../Traits/Pokemon/SetTrait.php');
require_once(__DIR__.'/../Traits/Pokemon/GetTrait.php');
 
// ポケモン
abstract class Pokemon
{

    use ResponseTrait;
    use InstanceTrait;
    use SetTrait;
    use GetTrait;
 
    /**
    * ニックネーム
    * @var string(min:1 max:5)
    */
    protected $nickname;
 
    /**
    * 現在のレベル
    * @var integer(min:2 max:100)
    */
    protected $level;
 
    /**
    * 覚えている技
    * @var array(min:1 max:4)
    */
    protected $move = [];
 
    /**
    * 経験値
    * @var integer
    */
    protected $exp;
 
    /**
    * 個体値
    * @var array(value min:0 max:31)
    */
    protected $iv = [
        'HP' => null,
        'Attack' => null,
        'Defense' => null,
        'SpAtk' => null,
        'SpDef' => null,
        'Speed' => null,
    ];
 
    /**
    * 努力値
    * @var array
    */
    protected $ev = [
        'HP' => 0,
        'Attack' => 0,
        'Defense' => 0,
        'SpAtk' => 0,
        'SpDef' => 0,
        'Speed' => 0,
    ];
 
    /**
    * インスタンス作成時に実行される処理
    *
    * @param object|array|null
    * @return void
    */
    public function __construct($before=null)
    {
        switch (gettype($before)) {
            /**
            * 捕まえた際の処理
            * @var null $before
            */
            case 'NULL':
            $this->setLevel();
            $this->setDefaultExp();
            $this->setDefaultMove();
            $this->setIv();
            $this->setMessage($this->name.'をゲットした', 'success');
            break;
            /**
            * 前の画面からの引き継ぎ
            * @var array $before
            */
            case 'array':
            $this->takeOverAbility($before);
            break;
            /**
            * 進化した際の処理
            * @var object $before
            */
            case 'object':
            // 進化前のポケモンと一致しているかチェック
            if(is_a($before, $this->before_class ?? null)){
                $this->takeOverAbility($before);
                // メッセージの引き継ぎ
                $this->setMessage($before->getMessages());
                $this->setMessage($this->name.'に進化した', 'success');
                $this->checkMove();
            }
            break;
        }
    }
 
    /**
    * レベルアップ処理
    *
    * @return void
    */
    protected function actionLevelUp()
    {
        // レベルアップ
        $this->level++;
        $this->setMessage($this->getNickName().'のレベルは'.$this->level.'になった!', 'success');
        // 現在のレベルで習得できる技があるか確認
        $this->checkMove();
    }
 
    /**
    * 進化
    *
    * @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');
        }
    }
 
    /**
    * 現在のレベルで覚えられる技があるか確認する処理
    *
    * @var integer
    */
    protected function checkMove()
    {
        // レベルアップして覚えられる技があれば習得する
        $level_move_keys = array_keys(array_column($this->level_move, 0), $this->level);
        foreach($level_move_keys as $key){
            $move_class = $this->level_move[$key][1];
            // 覚えようとしている技(クラス)が存在かつ重複していないか
            if(class_exists($move_class) && !in_array($move_class, $this->move, true)){
                // 技クラスをセット
                $this->setMove($move_class);
                // インスタンス化
                $move = new $move_class();
                $this->setMessage($move->getName().'を覚えた!', 'success');
            }
        }
    }
 
    /**
    * 現在インスタンスを出力
    *
    * @return array
    */
    public function export()
    {
        return [
            'class_name' => get_class($this),   # クラス名
            'nickname' => $this->nickname,    # ニックネーム
            'level' => $this->level,          # レベル
            'ev' => $this->ev,                # 努力値
            'iv' => $this->iv,                # 個体値
            'exp' => $this->exp,              # 経験値
            'move' => $this->move,            # 技
        ];
    }
 
    /**
    * 進化時の能力引き継ぎ処理
    *
    * @param object $before 進化前
    * @return void
    */
    protected function takeOverAbility($before)
    {
        if(is_object($before)){
            $this->nickname = $before->nickname;    # ニックネーム
            $this->level = $before->level;          # レベル
            $this->ev = $before->ev;                # 努力値
            $this->iv = $before->iv;                # 個体値
            $this->exp = $before->exp;              # 経験値
            $this->move = $before->move;            # 技
        }elseif(is_array($before)){
            $this->nickname = $before['nickname'];    # ニックネーム
            $this->level = $before['level'];          # レベル
            $this->ev = $before['ev'];                # 努力値
            $this->iv = $before['iv'];                # 個体値
            $this->exp = $before['exp'];              # 経験値
            $this->move = $before['move'];            # 技
        }
    }
}

 

コンストラクタ内でswitchを使い、引数で受け取ったbeforeの型をgettype関数を使ってチェックしています。 

 NULL → ゲット

array → 引き継ぎ

object → 進化

 

上記3つの判定になります。ただ、分岐が多くなりすぎるのも良くないので、そろそろメソッド分けする必要がありそうですが、一旦はこのまま押し通します。

 

次に新しく追加したexportというメソッドを見てみましょう。

/**
* 現在インスタンスを出力
*
* @return array
*/
public function export()
{
    return [
        'class_name' => get_class($this),   # クラス名
        'nickname' => $this->nickname,    # ニックネーム
        'level' => $this->level,          # レベル
        'ev' => $this->ev,                # 努力値
        'iv' => $this->iv,                # 個体値
        'exp' => $this->exp,              # 経験値
        'move' => $this->move,            # 技
    ];
}

 

これは、現在のポケモンの引き継ぎ用情報を出力するためのメソッドです。これを使い、セッションに必要なデータを渡します。引き継ぎ後はクラスを呼び出す必要があるため、クラス名をget_classで取得して配列に格納しています。

 

変更が加えられた、能力の引き継ぎメソッド(takeOverAbility)についても見てみましょう。

/**
* 進化時の能力引き継ぎ処理
*
* @param object $before 進化前
* @return void
*/
protected function takeOverAbility($before)
{
    if(is_object($before)){
        $this->nickname = $before->nickname;    # ニックネーム
        $this->level = $before->level;          # レベル
        $this->ev = $before->ev;                # 努力値
        $this->iv = $before->iv;                # 個体値
        $this->exp = $before->exp;              # 経験値
        $this->move = $before->move;            # 技
    }elseif(is_array($before)){
        $this->nickname = $before['nickname'];    # ニックネーム
        $this->level = $before['level'];          # レベル
        $this->ev = $before['ev'];                # 努力値
        $this->iv = $before['iv'];                # 個体値
        $this->exp = $before['exp'];              # 経験値
        $this->move = $before['move'];            # 技
    }
}

 

前回までは進化の際にしか能力値を引き継いでいませんでしたが、今回からは画面移管でも引き継ぐ必要があるので、配列で受け取った場合の処理を追加しました。これで、どちらのパターンでも同じメソッドを使った能力の引き継ぎが可能です。

 

それではコントローラーの修正箇所(コンストラクタ)を見ていきましょう。

 

コントローラー(/Classes/Controller.php
/**
* @return void
*/
public function __construct()
{
    $post = $_POST;
    $session = $_SESSION;
    // オートローダーの起動
    new AutoLoader();
    /**
    * 初期画面
    */
    if(empty($post)){
        $_POST = [];
        $_SESSION = [];
        return;
    }
    /**
    * ポケモンが選択された
    */
    if(isset($post['pokemon'])){
        $this->checkPokemon(htmlspecialchars($post['pokemon']));
        return;
    }
    /**
    * アクションが実行された
    */
    if(isset($post['action']) && class_exists($session['pokemon']['class_name'] ?? null)){
        // 引き継いだデータを引数にポケモンをインスタンス化
        $this->pokemon = new $session['pokemon']['class_name']($session['pokemon']);
        // アクションメソッドの実行
        $this->action(htmlspecialchars($post['action']), htmlspecialchars($post['param'] ?? null));
    }
}

 

前回までは引数でpostsessionを受け取っていましたが、正直グローバルでとっても問題なさそうなので変更しました。ただ、そのままは使用せずに一度変数に格納してから使っています。

 大きく変更されたのは、アクションが実行された際の処理です。今まではそのままpokemonのプロパティに渡していましたが、class_existsでチェックしてからインスタンス化するという手順を踏んでいます。

あと追加で、申し訳程度にhtmlspecialcharsを使ってサニタイズしています。

 

コントローラーの仕様に合わせて出力画面も修正します。

 

出力画面(/index.php
<?php
 
require_once(__DIR__.'/Classes/Controller.php');
require_once(__DIR__.'/Resources/Lang/Translation.php');
 
session_start();
 
$controller = new Controller();
$action_path = '/';
 
?>
<!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">
            <?php if(isset($controller->pokemon)): ?>
                <section>
                    <div class="row">
                        <div class="col-12 col-sm-6 col-md-4">
                            <?php # 詳細 ?>
                            <table class="table table-bordered table-hover">
                                <thead class="thead-light">
                                    <tr>
                                        <th scope="col" colspan="2">詳細</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <?php foreach($controller->pokemon->getDetails() as $key => $val): ?>
                                        <tr>
                                            <th scope="row" class="w-50"><?=transJp($key)?></th>
                                            <td><?=$val?></td>
                                        </tr>
                                    <?php endforeach; ?>
                                </tbody>
                            </table>
                        </div>
                        <div class="col-12 col-sm-6 col-md-4">
                            <?php # ステータス ?>
                            <table class="table table-bordered table-hover">
                                <thead class="thead-light">
                                    <tr>
                                        <th scope="col" colspan="2">ステータス</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <?php foreach($controller->pokemon->getStats() as $key => $val): ?>
                                        <tr>
                                            <th scope="row" class="w-50"><?=transJp($key)?></th>
                                            <td><?=$val?></td>
                                        </tr>
                                    <?php endforeach; ?>
                                </tbody>
                            </table>
                        </div>
                        <div class="col-12 col-sm-6 col-md-4">
                            <?php # 覚えている技 ?>
                            <table class="table table-bordered table-hover">
                                <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>
                        </div>
                    </div>
                </section>
            <?php endif; ?>
            <section>
                <div class="row">
                    <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/reset.php'); # リセット ?>
                        <?php else: ?>
                            <?php include('Resources/Partials/Forms/select_pokemon.php'); ?>
                        <?php endif; ?>
                    </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; ?>
                            <?php if(!empty($controller->getResponses())): ?>
                                <pre><?php var_export($controller->getResponses()); ?></pre>
                            <?php endif; ?>
                        </div>
                    </div>
                </div>
            </section>
        </div>
    </main>
</body>
</html>

 

 

日本語化の実装(おまけ)

 先程のindex.phpにも記述していますが、一部分だけ日本語化を実装しました。とは言っても、英語をキーとした日本語を配列として用意し、それを関数で呼び出してチェックしているだけです。

 

翻訳ファイル(/Resources/Lang/Translation.php
<?php
 
function transJp($str)
{
    $array = [
        'attack' => 'こうげき',
        'defense' => 'ぼうぎょ',
        'spatk' => 'とくこう',
        'spdef' => 'とくぼう',
        'speed' => 'ぼうぎょ',
        'name' => '正式名称',
        'nickname' => 'ニックネーム',
        'type' => 'タイプ',
        'level' => 'レベル',
        'exp' => '経験値',
        'nextlevel' => '次のレベルまで',
        'physical' => '物理',
        'special' => '特殊',
        'status' => '変化',
    ];
    // 小文字変換して配列から取得、存在しなければそのまま返却
    return $array[mb_strtolower($str)] ?? $str;
}

 

今まで日本語キーだった部分を英語に置き換え、それに合わせてtransJpという関数を呼び出す仕様です。もし技やポケモンの名前も、わざわざインスタンス化してgetNameをするのが面倒であれば、同じように用意して関数で置き換えるという方法をとっても構いません。

  

まとめ

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

今回のPHPポケモンでは、前回実装したオートローダーの不備を修正し、正しい使い方をご紹介しました。

ぜひオートローダーを使う人は、しっかり公式マニュアルや書籍を読み込んでから実装するようにしておきましょう。

パーフェクトPHP パーフェクトPHP

ワイがPHPを勉強した一冊や! というより、書籍はこれしか読んでないで! ちなみに、最初からこれに挑むとほぼ100%挫折するので、ある程度PHPを理解してからの方がいいぞ   オブジェクト指向がよく分かってなくて、関数がなんとなく理解出来てたあたりで読み出して、理解を深めた一冊や。 古い本やけど、...

 

注目の記事

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

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

【Adobe Animate CC】モーショントゥイーンを使ったアニメーション作成
動画編集
Adobe,Animate,Illustrator,Photoshop,アニメーション
【Adobe Animate CC】モーショントゥイーンを使ったアニメーション作成

    今回はキャラクターがうちわを扇いでいるアニメーションのAdobe Animateを使った作成方法をご紹介します。 完成イメージは以下の通りです。   Photoshopなどを使ってもgifアニメーションの作成はできますが、Adobe Animateのモーショントゥイーンを使えば、変化するポイントだけを設定す...

WordPressをローカルと本番環境で同じ状態にするために理解しておきたい3つのポイントを徹底解説
プログラミング
PHP,phpMyAdmin,WordPress
WordPressをローカルと本番環境で同じ状態にするために理解しておきたい3つのポイントを徹底解説

  WordPressで作ったサイトは通常のサイトと違い、DBが絡んでくるためローカル環境と本番環境を同一の状態で稼働させるには設定や更新されるディレクトリの知識が必要になります。 今回は、WordPressを使ったサイトを作成している人や、開発に挑戦しようとしている人に向けて、ローカルで作ったWordPressのサイ...

PHPポケモン「わざ編〜わるあがき〜」35
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「わざ編〜わるあがき〜」35

わるあがき そろそろ技のPPを実装段階にきたので、その前に「わるあがき」という技を作成しましょう。「わるあがきって何?」という人のために、どういった技なのか簡単に説明します。 全ポケモン使用可能。ただし、レベルアップなどで普通のわざとして覚えることはできず、自分の技がすべて選択不能になった場合...

PHPポケモン「コントローラー編」〜POSTとSESSIONの活用〜 10
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「コントローラー編」〜POSTとSESSIONの活用〜 10

  今回のPHPポケモンでは、今まで作った機能用のコントローラーになるインターフェースを作成します。ポケモンやメソッドを選択できるようにして、よりゲーム性の高いアプリケーションを実装しましょう。   第1回から学習したい方はコチラ     コントローラーの実装   それでは実装したアクション...

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

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

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

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

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

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

カテゴリ

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