プログラミング

へんしん編 PHPポケモン 74

PHP PHPポケモン ポケモン
へんしん編 PHPポケモン 74

へんしんとは

今回はサムネイルに合わせて、特別技の1つ「へんしん」を実装します。 

 

へんしんを使うことで、相手ポケモンをコピーすることができますが、その全てをコピーするわけではありません。コピーできる項目とそうでない項目は以下の通りです。

コピーできる項目

  • ポケモンの種族
  • HP以外のステータス
  • ランク補正
  • 倒した際の努力値
  • 基礎経験値
  • 努力値

コピーできない項目

  • HP
  • レベル
  • ニックネーム
  • 状態異常
  • 状態変化
  • 個体値

 

現在PHPポケモンで実装されている機能をまとめました。本来のポケモン仕様ではHPを除くステータス実数値を引き継ぐことになります。ですが、PHPポケモンでは実数値を保管せず、努力値・個体値・ランク補正を使って計算しているため、こちらは独自の仕様を入れながら作成していきます。

 

へんしん処理の流れ

まずはへんしん処理をする上での流れをまとめましょう。他の技と異なり、変更しなければいけない項目が多く、種族値などポケモンが持つ値を変更してしまうと、バトル終了判定で元に戻す項目が多くなります。そうなると、本来ではなり得ない状態が出来上がってしまうことにも繋がりますので、バトルで使用しているインスタンスを置き換えることで対応します。 

× へんしん後のポケモンに書き換え

○ バトルで使用するインスタンスを置き換え

 

インスタンスを置き換えるために、へんしんを使った際に「へんしん状態のポケモンオブジェクト」を呼び出す必要があります。通常のインスタンス作成では、HPの種族値など変更できない項目がいくつかあるので、こちらはへんしん専用のインスタンス作成処理を追加することで対応します。 

へんしん用インスタンスの作成

 

それでは、1つずつ処理を見ていきましょう。

 

コピーポケモンの作成

まずはコピーポケモンのインスタンス作成処理についてです。現在はポケモンオブジェクトを呼び出す際にレベルの指定のみを引数としていましたが、第2引数を追加して「へんしん」によるオブジェクト生成ができるようにしましょう。

 

 ポケモンクラス(/Classes/Pokemon.php)
// ポケモン
abstract class Pokemon
{
--省略
 
    /**
    * へんしんフラグ
    * @var boolean
    */
    protected $transform_flg = false;
 
    /**
    * インスタンス作成時に実行される処理
    * @param param:mixed
    * @param transform:object|null::Pokemon
    * @return void
    */
    public function __construct($param=null, $transform=null)
    {
        if(is_object($transform)){
            // へんしん用処理
            $this->transform($param, $transform);
        }else{
            // 初期化
            $this->init($param);
        }
    }

 

もし第2引数で対象のポケモンオブジェクトが指定されていた場合、へんしんの特別処理としてtransformのメソッドを呼び出しています。記述量が多いので、こちらはトレイト分けしました。

 

へんしん処理用トレイト(/App/Traits/Class/Pokemon/ClassPokemonTransformTrait.php
<?php
// へんしん処理専用トレイト
trait ClassPokemonTransformTrait
{
 
    /**
    * へんしんによるインスタンスの作成処理
    * @param pokemon:object::Pokemon
    * @param enemy:object::Pokemon
    * @return void
    */
    private function transform(object $pokemon, object $enemy)
    {
        // へんしんでコピーするステータス
        $this->rank = $enemy->getRank();                    # ランク
        $this->iv = $enemy->getIv();                        # 個体値
        $this->ev = $enemy->getEv();                        # 努力値
        $this->move = $enemy->getMove(null, 'array');       # 覚えている技
        // へんしんでコピーされないステータス
        $this->level = $pokemon->getLevel();                # レベル
        $this->sa = $pokemon->getSa();                      # 状態異常
        $this->sc = $pokemon->getSc();                      # 状態変化
        $this->position = $pokemon->getPosition();          # 立場
        $this->nickname = $pokemon->getNickName();          # ニックネーム
        $this->remaining_hp = $pokemon->getRemainingHp();   # 残りHP
        $this->exp = $pokemon->getExp();                    # 現在の経験値
        /**
        * へんしん時に書き換えする処理
        */
        // へんしんフラグ
        $this->transform_flg = true;
        // HPは元ポケモンのステータスを引き継ぐ
        $this->base_stats['HP'] = $pokemon->getBaseStats()['HP'];
        $this->iv['HP'] = $pokemon->getIv()['HP'];
        $this->ev['HP'] = $pokemon->getEv()['HP'];
        // 技の残りPPを5にする
        $this->move = array_map(function($move){
            $move['remaining'] = 5;
            return $move;
        }, $this->move);
        // 覚える技・進化レベルを空にする(念の為)
        $this->level_move = [];
        if(isset($this->evolve_level)){
            $this->evolve_level = null;
        }
    }
}

 

ステータスの実数値を引き継げるように、個体値・努力値は相手ポケモンのものを受け取っていますHPのステータス変更は入らないため、書き換え後に上書きで自ポケモンのものと置き換えています。

また、へんしん後にレベルアップ処理が入った際にも同様の演出ができるように、現在の経験値も元ポケモンから引き継いでいます。

技のPPはへんしん後にオール5になるので、array_mapを使って書き換えています。

 

プロパティの置き換え

現在バトルコントローラーで使用してるポケモンのオブジェクトは、pokemonというプロパティに格納されています。こちらを置き換えることで、元ポケモンのオブジェクトはparty内、バトル用はpokemonというように扱い、元オブジェクトを書き換えることなく処理をします。

 

バトルコントローラー用トレイト(/App/Traits/Controller/BattleControllerTrait.php
/**
* 引き継ぎ処理
* @return void
*/
protected function inheritance()
{
    // バトル状態の引き継ぎ
    if(isset($_SESSION['__data']['battle_state'])){
        $battle_state = unserializeObject($_SESSION['__data']['battle_state']);
        // ターン最初の状態へ初期化
        $battle_state
        ->turnInit();
        // グローバルにセット
        setBattleState($battle_state);
    }else{
        // バトル状態の初期化
        initBattleState();
    }
    // ポケモン番号の引き継ぎ
    $this->order = $_SESSION['__data']['order'];
    // 敵ポケモンの引き継ぎ
    if(isset($_SESSION['__data']['enemy'])){
        $this->enemy = unserializeObject($_SESSION['__data']['enemy']);
        // 前ターンの状態をプロパティに格納
        $this->before['enemy'] = clone $this->enemy;
    }
    // 戦闘中のポケモンをプロパティにセット
    $transform = getBattleState()->getTransform('friend');
    if($transform){
        // へんしん状態の場合はBattleStateからポケモン情報を取得
        $this->pokemon = $transform;
    }else{
        $this->pokemon = $this->party[$this->order];
    }
    // 前ターンの状態をプロパティに格納
    $this->before['friend'] = clone $this->pokemon;
}

 

もしへんしん状態であれば、格納するオブジェクトをパーティーからではなく、バトル状態へ格納したポケモンオブジェクトから参照するように分岐をさせました。

 

バトル状態クラス(/Classes/BattleState.php
<?php
/**
* バトル状態クラス
*/
class BattleState
{
 
--省略
 
    /**
    * へんしん情報
    * @var array
    */
    private $transforms;
 
 
    /**==================================================================
    * 初期化・初期値
    ==================================================================**/
 
    /**
    * 初期化
    * @return void
    */
    public function init() :void
    {
        $this->run = 0;
        $this->dafaultFields();
        $this->dafaultTurnDamages();
        $this->dafaultTransforms();
        $this->dafaultLastMoves();
    }
 
--省略
 
    /**
    * へんしん状態の初期値
    * @return void
    */
    public function dafaultTransforms() :void
    {
        $this->transforms = [
            'friend' => [],
            'enemy' => [],
        ];
    }
 
--省略
    /**==================================================================
    * へんしん状態
    ==================================================================**/
 
    /**
    * へんしん状態の格納
    * @param pokemon:object::Pokemon
    * @param enemy:object::Pokemon
    * @return object::Pokemon
    */
    public function setTransform(object $pokemon, object $enemy): object
    {
        $class = get_class($enemy);
        $this->transforms[$pokemon->getPosition()] = new $class($pokemon, $enemy);
        // へんしん後のポケモンインスタンスを返却
        return $this->transforms[$pokemon->getPosition()];
    }
 
    /**
    * へんしん状態の取得
    * @param position:string::friend|enemy
    * @return mixed
    */
    public function getTransform(string $position)
    {
        return $this->transforms[$position];
    }
   
}

 

へんしん状態でレベルアップ処理や状態異常の処理が入った場合、両方に同じように処理を加える必要があります。なので、こちらはそれぞれ処理終了直前に整合性を取るための処理を追加します。

 

バトルコントローラー用トレイト(/App/Traits/Controller/BattleControllerTrait.php
/**
* バトル結果判定
*
* @return void
*/
private function judgment()
{
    if($this->fainting['friend']){
        // 味方がひんし状態になった
        setMessage('目の前が真っ暗になった');
    }else{
        // 相手がひんし状態になった(味方はひんし状態ではない)
        // 経験値の計算
        $exp = $this->calExp($this->pokemon, $this->enemy);
        // 経験値をポケモンにセット
        $this->party[$this->order]
        ->setExp($exp);
        // 努力値を獲得
        $this->party[$this->order]
        ->setEv($this->enemy->getRewardEv());
        // もしポケモンが「へんしん状態」であれば変更後の状態を引き継ぎ
        if($this->pokemon->checkSc('ScTransform')){
            $this->pokemon
            ->judgmentTransform($this->party[$this->order]);
        }
    }
    // 散らばったお金の取得
    $money = getBattleState()->getMoney();
    if($money){
        setMessage($this->player->getName().'は、'.$money.'円拾った');
        $this->player
        ->addMoney($money);
    }
    // バトル終了判定用メッセージの格納
    setEmptyMessage('battle-end');
}
 
/**
* デストラクタ直前の処理
* @return void
*/
private function checkBeforeDestruct()
{
    $transform = getBattleState()->getTransform('friend');
    // もし「へんしん状態」であれば、残HPと状態異常を元ポケモンに反映
    if($transform){
        $this->party[$this->order]
        ->mirroringTransform($transform);
    }
}

 

へんしん用トレイト(/App/Traits/Class/Pokemon/ClassPokemonTransformTrait.php
/**
* へんしん状態のステータスを元ポケモンに反映させる処理
* @param trans_pokemon:object::Pokemon
* @return void
*/
public function mirroringTransform(object $trans_pokemon)
{
    if($this->checkSc('ScTransform')){
        $this->sa = $trans_pokemon->getSa('all');                 # 状態異常
        $this->remaining_hp = $trans_pokemon->getRemainingHp();   # 残HP
    }
}
 
/**
* バトル判定後の状態をへんしん状態のポケモンに反映させる処理
* @param base_pokemon:object::Pokemon
* @return void
*/
public function judgmentTransform(object $base_pokemon)
{
    $this->ev = $base_pokemon->getEv();         # 努力値
    $this->level = $base_pokemon->getLevel();   # レベル
    $this->exp = $base_pokemon->getExp();       # 経験値
}

 

レベルアップ処理については、パーティー内のオブジェクトに対して直接処理を行い、へんしんポケモンには値のみを引き継ぐようにしています。

状態異常と残りHPはへんしんポケモンを基準として、パーティー内の元ポケモンに値を反映させました。これで、両方が同じ状態で進行するように整合性を保っています。

 

次に、バトル処理中のオブジェクトについてです。もしへんしんを先手で発動した場合、防御ターンにそのタイプやステータスが反映されている必要があります。オブジェクトは参照されていますが、プロパティの値そのものが変更される場合は、既に配列に格納されたオブジェクトからはアクセスができなくなってしまいます。

なので、バトル処理内でも「へんしん」が行われたかを判定するための分岐を追加して、プロパティ自体を変更しましょう。

 

たたかう用サービス(/App/Services/Battle/FightService.php
/**
* 行動順に攻撃処理
*
* @return boolean (false: ひんしポケモン有り)
*/
private function actionAttack($orders)
{
    foreach($orders as list($atk, $def, $move)){
        // 攻撃ポケモンの怒り解除
        $atk->releaseSc('ScRage');
        // 先手が「へんしん」を使って成功した場合のオブジェクト置き換え処理
        if(!$def->getTransformFlg() && $def->checkSc('ScTransform')){
            // 防御ポケモンのへんしんフラグがfalse且つ、状態変化で「へんしん」がセットされている場合
            $def = $this->battle_state
            ->getTransform($def->getPosition());
        }
        // 攻撃(返り値に使用した技を受け取る)
        $attack_move = $this->attack($atk, $def, $move);
        // 最後に使用した技を格納
        $this->battle_state
        ->setLastMove($atk->getPosition(), $attack_move);
        // バトル終了のレスポンスチェック(交代技など)
        if(getResponse('end')){
            break;
        }
        // ひんしチェック
        $this->fainting = [
            $atk->getPosition() => $this->checkFainting($atk),
            $def->getPosition() => $this->checkFainting($def),
        ];
        // どちらかがひんし状態なら処理終了
        if($this->fainting['friend'] || $this->fainting['enemy']){
            $result = false;
            break;
        }
    } # endforeach
    // 結果返却
    return $result ?? true;
}

 

これで、プロパティの値を変更する処理が整いました。

 

へんしんの特別処理

次に、へんしんを使った際の特別処理を見ていきましょう。まずは、技クラスと状態変化クラスについてです。

 

へんしん:技(/Classes/Move/MoveTransform.php
<?php
$root_path = __DIR__.'/../..';
require_once($root_path.'/Classes/Move.php');
 
// へんしん
class MoveTransform extends Move
{
 
    /**
    * 正式名称
    * @var string
    */
    protected $name = 'へんしん';
 
    /**
    * 説明文
    * @var string
    */
    protected $description = '相手のポケモンに変身する。';
 
    /**
    * タイプ
    * @var string
    */
    protected $type = 'TypeNormal';
 
    /**
    * 分類
    * @var string(physical:物理|special:特殊|status:変化)
    */
    protected $species = 'status';
 
    /**
    * 威力
    * @var integer|null
    */
    protected $power = null;
 
    /**
    * 命中率
    * @var integer|null
    */
    protected $accuracy = null;
 
    /**
    * 使用回数
    * @var integer
    */
    protected $pp = 10;
 
    /**
    * 対象
    * @var string
    */
    protected $target = 'enemy';
 
    /**
    * へんしんの専用効果
    * @param atk:object::Pokemon
    * @param def:object::Pokemon
    * @param battle_state:object::BattleState バトル状態
    * @return void
    */
    public function exTransform(object $atk, object $def, object $battle_state)
    {
        if(!$atk->checkSc('ScTransform')){
            // 現在へんしん状態でなければ実行
            $atk->setSc('ScTransform', 0, get_class($def)); # 先に状態変化(へんしん)をセット
            $battle_state->setTransform($atk, $def);
            return true;
        }else{
            // 現在へんしん状態であれば失敗
            return false;
        }
    }
 
}

 

へんしん:状態変化(/Classes/StateChange/ScTransform.php
<?php
$root_path = __DIR__.'/../..';
require_once($root_path.'/Classes/StateChange.php');
 
// へんしん
class ScTransform extends StateChange
{
 
    /**
    * 正式名称
    * @var string
    */
    protected $name = 'へんしん';
 
}

 

へんしんオブジェクトを作成する際に状態変化をコピーしているため、オブジェクト生成前に状態変化をセットしています。へんしんループを防ぐために、PHPポケモンではへんしん状態からのへんしんは失敗するようにしました。

 

次に、攻撃トレイト内での処理について見てみましょう。

 

攻撃トレイト(/App/Traits/Service/Battle/ServiceBattleAttackTrait.php
// attackメソッド内
//
// 攻撃メッセージを格納
$this->atk_msg_id = issueMsgId();
setMessage(
    $atk_pokemon->getPrefixName().'は'.$move->getName().'を使った!',
    $this->atk_msg_id
);
// 「へんしん」の特別処理
if(get_class($move) === 'MoveTransform'){
    $this->exTransform($atk_pokemon, $def_pokemon, $move);
    return $move;
}

 

へんしん使用メッセージは必要になるため、攻撃メッセージ生成直後に返信の特別処理を呼び出しています。

 

特別処理用トレイト(/App/Traits/Service/Battle/ServiceBattleExTrait.php
/**
* へんしんの特別処理
*
* @param atk:object::Pokemon
* @param def:object::Pokemon
* @param move:object::Move
* @return void
*/
protected function exTransform(object $atk, object $def, object $move): void
{
    // へんしんの特別処理を呼び出し
    $result = $move->exTransform($atk, $def, $this->battle_state);
    if($result){
        // へんしん
        setResponse([
            'param' => get_class($def),
            'action' => 'transform',
            'target' => $atk->getPosition(),
        ], $this->atk_msg_id);
        // 成功
        setMessage($atk->getPrefixName().'は'.$def->getName().'にへんしんした');
        // プロパティの書き換え
        if($atk->getPosition() === 'friend'){
            // 味方
            $this->pokemon = $this->battle_state
            ->getTransform('friend');
        }else{
            // 相手
            $this->enemy = $this->battle_state
            ->getTransform('enemy');
        }
    }else{
        // 失敗
        setMessage('しかし上手く決まらなかった');
    }
}

 

へんしん後はポケモンの画像を変更する必要があるので、レスポンスには対象ポケモンのクラス名、actiontransformtargetに自身を選択しています。サービス自体のプロパティの置き換え処理は、このタイミングで行っています。

 

画像の置き換え

次に画像の置き換え処理についてです。こちらはjsでレスポンスの値に合わせてsrcを書き換えます。現在のポケモンの判定がしやすいように、data要素として現在のポケモンクラスを持たせました。

 

バトル画面(/Resources/Page/Battle.php
<?php # 自ポケモン詳細 ?>
<div class="col-6 text-center">
    <input type="image"
    id="friend-pokemon-image"
    class="action-img-btn"
    src="/Assets/img/pokemon/dots/back/<?=get_class($before_pokemon)?>.gif"
    alt="<?=$before_pokemon->getName()?>"
    data-pokemon="<?=get_class($before_pokemon)?>"
    data-toggle="modal"
    data-target="#friend-battle-state-modal" />
</div>

 

バトルメッセージ用JS/Public/Assets/js/Battle/message.js
// ==============================================
// へんしん処理 =================================
//
/**
* @param json
* @return Promise
**/
var doAnimateTransform = function (target, param){
    return new Promise ((resolve, reject) => {
        // 対象のポケモン画像を指定
        var img = $('#' + target + '-pokemon-image');
        // へんしん前のポケモンクラスを取得
        var before = img.data('pokemon');
        // srcを書き換える
        var src = img.attr('src').replace(before, param);
        img.attr('src', src);
        resolve();
    });
}

 

メッセージのアクション分岐にtransformを追加し、へんしん用のアニメーション処理へ分岐させるようにしました。jsでの処理は画像を変更するだけなので、受け取ったポケモンクラスを、現在のポケモンクラスと置き換えるように、srcに対してreplaceをして新しい画像パスへと変更しています。

 

では、実際にへんしんによる技効果を見てみましょう。

 

しっかり対象ポケモンにへんしん、技を引き継ぐことができました。

 

メタモンの作成

へんしんを追加することができたので、ここで久々に新しいポケモン「メタモン」を追加しましょう。

 

メタモン(/Classes/Pokemon/Metamon.php
<?php
require_once(__DIR__.'/../Pokemon.php');
 
// メタモン
class Metamon extends Pokemon
{
 
    /**
    * 正式名称
    * @var string(min:1 max:5)
    */
    protected $name = 'メタモン';
 
    /**
    * ニックネーム
    * @var string(min:1 max:5)
    */
    protected $nickname = '';
 
    /**
    * タイプ
    * @var array
    */
    protected $types = ['TypeNormal'];
 
    /**
    * 初期レベル
    * @var array
    */
    protected $default_level = [
        5
    ];
 
    /**
    * 基礎経験値
    * @var integer
    */
    protected $base_exp = 101;
 
    /**
    * レベルアップで覚える技
    * @var array
    */
    protected $level_move = [
        [1, 'MoveTransform'],             # へんしん
    ];
 
    /**
    * 種族値
    * @var array
    */
    protected $base_stats = [
        'HP' => 48,
        'Attack' => 48,
        'Defense' => 48,
        'SpAtk' => 48,
        'SpDef' => 48,
        'Speed' => 48,
    ];
 
    /**
    * 獲得努力値
    * @var array
    */
    protected $reward_ev = [
        'HP' => 1,
    ];
 
}

 

技はへんしんのみです。実際に相手がへんしんを使った場合でも、正常な処理がされるかどうかを検証するために用意しました。では、相手ポケモンとしてメタモンを登場させて戦ってみましょう。

  

こちらが持っている技をコピーして戦っていることが確認できました。へんしん後は獲得努力値と経験値も引き継いでいるため、それぞれが高いポケモンで挑めば効率よく稼ぐことができます。しかし技構成がコピーされてしまうため、HPの状態やレベル、急所の発動頻度によっては自分の首を締める結果にもなるので注意が必要です。

 

メタモンについては、近々本番環境へも反映予定ですので、ぜひ遊んでみてくださいね。

 

まとめ

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

今回のPHPポケモンでは「へんしん」の実装方法をご紹介しました。

ポケモンに興味がある方、プログラミング学習に挑戦しようと考えている方は、ぜひ参考にしてみてくださいね。

 

注目の記事

成功に近い3つの思考「楽して稼ぐ」「知識オタク」「資産形成は無駄」
雑記
成功に近い3つの思考「楽して稼ぐ」「知識オタク」「資産形成は無駄」

  「楽して稼ぎたい」   人間誰しも、そう考えているはずです。これは正しく、成功するためには必要な思考です。 それを「楽に稼ぐ方法なんてない」と無理やり押さえつけてしまう人は、完全に本質が見えておらず、その大半に「楽して稼げない自分を認められてない」というマイナス因子が含まれてい...

トレーナー戦編 バトルシステムへの追加 PHPポケモン 98
プログラミング
PHP,PHPポケモン,ポケモン
トレーナー戦編 バトルシステムへの追加 PHPポケモン 98

トレーナー戦闘の追加 前回トレーナー情報を作成したので、今回はその情報をバトルシステムへ組み込んでいきます。 現在、野生ポケモンとの戦闘では「battle」という値actionの値で受け取っています。同じサービス内で分岐を作ると複雑になってしまうので、battle_trainerという新しい分岐を使ってサービス分けをし...

なぜプロは有線のマウスやキーボードを選ぶのか?【有線VS無線】
雑記
Bluetooth
なぜプロは有線のマウスやキーボードを選ぶのか?【有線VS無線】

  無線が普及する現代、何故有線のマウスやキーボードは売れているのか   いろんなものが製品の進化と共に無線化している一方、有線の需要も高く、とくにプロなど上層で活躍する人は有線を選択するケースが少なくありません。 今回は、そんな有線と無線の違いや、それぞれのメリットについて解説していき...

SEが心がけるべき3つの習慣
プログラミング
Automator,JavaScript,エンジニア,システムエンジニア,プログラマー,プログラミング
SEが心がけるべき3つの習慣

  ネット社会、在宅ワークが主流になってきた今、SEという仕事に憧れを頂いている人は多くなりました。 単価の良さも、魅力の一つです。そして、技術が普及してきたことにあわせて、便利なソフトやアプリが簡単に手に入るようになり、一昔前と比べると技術の習得も容易になりました。   しかし、多くの人が...

たった10分!?読むだけでプログラミングが上達する3原則
プログラミング
jQuery,プログラミング学習,初心者
たった10分!?読むだけでプログラミングが上達する3原則

  プログラミングがなかなか身につかない   学習をしているけど、自分で書くとなれば思うようにいかなかったり、覚えたはずなのにその使い方や応用方法がわからない人のほとんどが、作り方そのものが間違っている傾向にあります。   今回は、プログラミング初学者や、なかなかスキルアップができない人...

簡単に良質なブログ記事を量産する3箇条【ネタがないとは言わせない】
ライティング
ブロガー,ブログ
簡単に良質なブログ記事を量産する3箇条【ネタがないとは言わせない】

  ブログの毎日のテーマ決めが大変・・・ そもそも良質な記事をどうやって書けるようになるのかわからない   こんな悩みを抱えていませんか? 始めたばかりで伸び悩んでいる人には多いのではないでしょうか。 今回はブログで収益化や、アクセス数を伸ばそうと考えている人へ向けて「簡単に良質なブログ...

初心者向けのブログで稼ぐ方法【アフィリエイト編:Google AdSense】
SEO対策
Google AdSense,アフィリエイト,クリック単価,クリック数,ブログ,広告収入
初心者向けのブログで稼ぐ方法【アフィリエイト編:Google AdSense】

  ブログを始めたほとんどの人が アフィリエイトで稼ぎたい   という強い思いを持っているのではないでしょうか。しかし現実は厳しく、広告の審査さえ通らず挫折してしまうといったことは多いです。 中には審査が通っているが、全然広告収入が得られないという人もいるでしょう。 毎日ブログを書いているの...

フリーランスのための値段交渉術!案件はこうやって見極めろ
フリーランス
フリーランスのための値段交渉術!案件はこうやって見極めろ

  「これもっと安くならない?」 「他の人はこれぐらいの金額でやってくれるよ」   こういった値切り交渉を受けたことがある人もいるのではないでしょうか?技術を提供するフリーランスであれば、金額を落とすということは自分の価値を下げているということを理解しておかなければなりません。 値段交渉...

カテゴリ

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