コマンドモード


コマンドモード

요청 자체를 캡슐화하는 것이다. 이를 통해 요청이 서로 다른 사용자를 매개변수
로 만들고, 요청을 대기시키거나 로깅하여, 되돌릴 수 있는 연산을 지원한다.

*GoF의 디자인 패턴 발췌
説明が難解だ.100回見ても理解できない説明が何ができるのか.百聞は一見にしかず、例題で見てみましょう.

みんなが一度やったゲーム英雄連盟では、ユーザー入力はいくつかの状況に限られている.キャラクタのマウス操作を移動したり、道具を使ったり、スキル操作をしたりします.
このスキル操作は、英雄連盟で最もよく使われるプレイヤーだと自信を持って言える.技能操作インタフェースはQ,W,E,R入力とスペル担当者D,Fに分けられる.
では、もし私たちがそれを実現したら、私たちはどのように設計しますか?以下の例を見てみましょう.
void PlayerInput::handleInput() {
	if(pressed(Q)) rangerFocus();
    else if(pressed(W)) volley();
    else if(pressed(E)) hawkshot();
    else if(pressed(R)) crystalArrow();
}
見るからに何をするかわかる.しかし、この方式には問題がある.考えてみれば、普通のゲームは身長を変えることができます.すなわち,入力キーの構造を変えることは困難である.
以下の方法を見てみましょう.
class Command {
public:
	virtual ~Command() { }
	virtual void execute() = 0;
};
まず,コマンドに対する純粋な仮想関数クラスを実装する.
class TigerStance : public Command {
public:
	virtual void execute() { tigerBuff(); }
    //Udyr stance change
};
それぞれの行為に合致する行為準則を体現している.
class PlayerInput {
public:
	void handleInput();
private:
	Command* qSkill;
    Command* wSkill;
    Command* eSkill;
    Command* rSkill;
};

void PlayerInput::handleInput() {
	if(pressed(BUTTON_Q) qSkill->execute();
    else if(pressed(BUTTON_W) wSkill->execute();
    else if(pressed(BUTTON_E) eSkill->execute();
    else if(pressed(BUTTON_R) rSkill->execute();
}
ここまで、これらはカスタムモードのコアコンテンツです.

コマンドモード-アクション


しかし、上の例から見ると、少し調和がとれていない.プレイ中のキャラクタに対するグローバル変数という仮定があります.これは柔軟性に欠ける方法です.以下の方法を見てみましょう.
class Command {
public:
	virtual ~Command() { }
    virtual void execute(Champion& champ) = 0;
};
Championオブジェクトを入力として受け入れ,チャンピオンスキルを用いてアクセスする.
class QSkillCommand : Command {
public:
	virtual void execute(Champion& champ) {
    	champ.qSkill();
    }
};
これによりチャンピオンのスキルを活用することが可能になった.しかし、このような例も少し違和感があります.一般的に、プレイヤーが操作するチャンピオンは変わりません.セラスやヴィエゴのように例外はあるが、ほとんどが固定優勝を操作する.
でもAIを考えてみます.AIは通常、Agentオブジェクトの作成および処理に使用され、インタフェースエージェントモードを使用してこれらのAgentを制御することもできます.