タグ

ブックマーク / toburau.hatenablog.jp (22)

  • Interpreter - ゲームが作れるようになるまでがんばる日記

    文法解析を反映したクラス構造。 簡単に言ってしまえば、BNFで文法を定義し、それを構文解析するということ。それのクラス表現をどうするかということ。 Interpreterがデザインパターンのなかに入っているとは思わなかった。BNFでしっかり定義できてしまえば、あとはその通りにコーディングすればよいから、それほど難しくはない。BNFでもれや矛盾がないようにしっかり定義するほうが大変だと思う。 ゲームでの応用はやっぱりスクリプトだろう。イベントシーンの記述や敵キャラクターAIの定義などさまざまな点で役に立つ。 しかし今はフリーですばらしいスクリプト言語がいくつも公開されているので、わざわざ新たに自分で作る必要は無いだろう。作るとしたらライセンスの問題とか、高機能すぎて向かないとかだろうか。 それでも、新たな言語を作るというのは魅力的である。いつかは自分で作るゲームでちょっとした部分で使ってみた

    Interpreter - ゲームが作れるようになるまでがんばる日記
  • Command - ゲームが作れるようになるまでがんばる日記

    メソッドを呼ぶということ自体をクラスにしてしまう。 あるクラスの処理を実行するにはクラスのメソッドを呼ぶ。その呼ぶということ自体をクラスで表現してしまうのがこのCommandパターン。あるクラスへの要求自体をクラスにしてしまえば、そのインスタンスを集めれば履歴として利用できる。クラスの種類を増やすことによって異なった要求にも対応できる。 CommandはEventと呼ばれることもある。GUIのアプリケーションを作成するときにでてくるイベントと同じ。 ゲームではAIの思考ルーチンをCommandで実装すると良いかもしれない。基的で単純な行動、たとえば歩く、撃つ、防御するなどをコマンドとして実装し、それらを組み合わせて複雑な行動を実現する。そのコマンドを組み合わせる部分のインタフェースを実装すればユーザーが独自でAIを作り上げることも出来る。 // コマンドのインタフェース public i

    Command - ゲームが作れるようになるまでがんばる日記
  • Proxy - ゲームが作れるようになるまでがんばる日記

    代理人が処理を代行。 インスタンスの生成に時間がかかるようなものはまず代理人で処理を代行し、代理人では実行できない要求がきたときに実際のインスタンスを生成する。 またWebのProxyサーバーのようにアクセス要求がきたとき、そのページをキャッシュしてあったときはそれを使い、キャッシュしていない場合は当のWebサーバーにアクセスする。 ゲームではRPGのステータス表示のメニューに使えそうだ。ステータス表示でカーソル位置によってはモデルデータも表示するような場合、どうしてもモデルデータの読み込みに時間がかかる。そこでProxyでまずパラメータを表示しておいて、モデルデータは必要になってから表示する。 // ステータスを表示するインタフェース public interface Status { public abstract void printStatus(); public abstrac

    Proxy - ゲームが作れるようになるまでがんばる日記
  • Flyweight - ゲームが作れるようになるまでがんばる日記

    インスタンスを共有して無駄をなくす。Flyweightとは「フライ級」のこと。 同じように使いまわせるインスタンスは無駄にnewせずに、最初に作成したものを共有してリソースを節約する。 ゲームではモデルデータやテクスチャデータの扱いにこのFlyweightパターンを使うことが多いだろう。 // モデルデータ管理クラス public class ModelDataManager { private Hashtable pool = new Hashtable(); public ModelData getModelData(String modelname) { ModelData md = (ModelData)pool.get(modelname); if (md == null) { md = new ModelData(modelname); pool.put(modelname,

    Flyweight - ゲームが作れるようになるまでがんばる日記
  • State - ゲームが作れるようになるまでがんばる日記

    状態をクラスとして表現するもの。 これはゲームプログラムでは定番の処理。タイトル、ゲーム中、ゲームオーバーなどの状態をクラスで表現し、それらを切り替えて使用する。 // 状態を表すインタフェース public interface State { public abstract void proc(Context context); public abstract void draw(Context context); } // タイトルを表すクラス public class Title implements State { private static Title singleton = new Title(); private Title() { } public static State getInstance() { return singleton; } public void p

    State - ゲームが作れるようになるまでがんばる日記
  • Memento - ゲームが作れるようになるまでがんばる日記

    直訳すると「記念品」「思い出」という意味。今の状態を保存しておいて、復帰できるようにする。 ゲームで言えばセーブ。今のプレイ状況を保存しておくこと。 以下、プレイヤーデータのHPとMPを保存して復帰する簡単なサンプル。 // セーブデータ(Memento役、記念品) SaveData.java package player; public class SaveData { int hp; int mp; SaveData(int hp, int mp) { this.hp = hp; this.mp = mp; } } // プレイヤーデータ(Originator役、作成者) Player.java package player; public class Player { private int hp; private int mp; public Player(int hp, int

    Memento - ゲームが作れるようになるまでがんばる日記
  • Observer - ゲームが作れるようになるまでがんばる日記

    観察者という意味。観察対象の状態が変化したら、観察者に対して通知する。 Model View Controller(MVC)のモデルとビューの関係といったほうが分かりやすいかも。内部データを持つ部分(モデル)と表示する部分(ビュー)を分け、モデルの内部データが更新されたら、ビューに通知して表示を更新する。Observerパターンはその関係と同じ。 RPGゲームでダメージを受けたときに、そのダメージの値をメッセージでログに出力するのと画面に描画する場合を考えてみた。 // Observerの抽象クラス Observer.java public interface Observer { public abstract void update(Parameter parameter); } // パラメータを表す抽象クラス Parameter.java import java.util.Vect

    Observer - ゲームが作れるようになるまでがんばる日記
  • Mediator - ゲームが作れるようになるまでがんばる日記

    読み方はメディエイター。仲介者、調停者、まとめ役のこと。 2つのオブジェクトがそれぞれ連携しあって動作するような場合、それぞれのオブジェクトが別のオブジェクトを監視していればよい。ところがもっと数が増え、3つ、4つになってくると大変である。そこでまとめ役のオブジェクトを用意し、まとめ役がそれぞれのオブジェクトに対して指示を出す。それぞれのオブジェクトはまとめ役からのみ指示を受けるようにする。 たとえば、RPGゲームで手に持つアイテムを選択するメニューの場合。片手剣、両手斧、盾の3種類あったとして、剣を選んだときは斧は選べなくなり、斧を選んだら剣、盾の両方が選べなくなる。このようにメニューの項目が連動するような場合にまとめ役となるMediatorを用意すればよい。 Mediator.java まとめ役 public interface Mediator { public abstract

    Mediator - ゲームが作れるようになるまでがんばる日記
  • Facade - ゲームが作れるようになるまでがんばる日記

    読み方はファサード。複数のクラスを組み合わせて使う場合にそれらをまとめたクラスを作り、それを窓口として使うこと。 例えば、クラスAとクラスBを組み合わせて使う場合に、クラスAのメソッドを呼んでからクラスBのメソッドを呼ばなくてはならないという順番に決まりがあるとする。このときにFacadeクラスを作成し、そのメソッド内でクラスAとクラスBを順番に呼ぶようにする。Facadeクラスを使えばクラスAとクラスBを使うときの決まりごとを知る必要はなくなる。 ClassA.java package Test; class ClassA { void exec() { ... } } ClassB.java package Test; class ClassB { void exec() { ... } } Facade.java package Test; public class Facade {

    Facade - ゲームが作れるようになるまでがんばる日記
  • Chain of Responsibility - ゲームが作れるようになるまでがんばる日記

    直訳すれば「責任の鎖」。受け取った処理が自分で解決できるなら解決し、解決できない場合は次へ回すという、行ってみればたらい回し。 とある処理を解決する方法が何種類かある場合、処理をリストでつなげておけば、どの処理を使うのか使う側が選択せずに、リストの先頭に任せてしまえばよい。これで使う側がどんな処理があるのかなど詳しく知らなくても済む。 public abstract class Handler { private Handler next; // 次に回すHandlerを設定するメソッド public Handler setNext(Handler next) { this.next = next; return next; } // 処理を受け取るメソッド public final void request(Param param) { if (exec(param)) { // 処理で

    Chain of Responsibility - ゲームが作れるようになるまでがんばる日記
  • Visitor - ゲームが作れるようになるまでがんばる日記

    データ構造を持つクラスとそれに処理を行うクラスを分離する。 データのクラスに行いたい処理のメソッドを追加するのではなく、処理を行うクラスを作成し、それを受け入れるようにする。こうすることにより処理内容が変わってもデータのクラスを修正する必要が無くなる。 さて、ゲームで考えてみよう。 武器や防具のアイテムを表すクラスとそれに対して何か処理を行うクラスに分けてみる。 Visitor.java 処理を行う抽象クラス public abstract class Visitor { public abstract void visit(Weapon weapon); public abstract void visit(Armor armor); } Acceptor.java 処理を行う抽象クラスVisitorを受け取るインタフェース public interface Acceptor { pub

    Visitor - ゲームが作れるようになるまでがんばる日記
  • Decorator - ゲームが作れるようになるまでがんばる日記

    中身と装飾を同一視して、重ねて装飾を追加していく。 Decoratorとは装飾者のことで、ケーキのデコレーションのように飾っていくこと。 ゲームで考えてみよう。 RPGでの武器に魔力が追加されたり、強さが+1とかに強化される状態を表現する。 Weapon.java 中身と装飾を同一視するための抽象クラス public abstract class Weapon { public abstract String getName(); public final void disp() { System.out.println(getName()); } } WeaponName.java 中身となる武器の名前。名前を指定してインスタンスを作成する。 public class WeaponName extends Weapon { private String name; public Weap

    Decorator - ゲームが作れるようになるまでがんばる日記
  • Composite - ゲームが作れるようになるまでがんばる日記

    容器と中身を同一視することにより、再帰的に扱えるようにする。 一番分かりやすい例としてはファイルシステムだろう。ファイルとディレクトリを共通のインタフェースを持つ親クラスから派生するようにする。そうすればディレクトリの中にさらにディレクトリがあっても、ファイルがあっても同じように扱うことができるし、再帰的にディレクトリの中を検索していくことができる。 その他、ウィンドウシステムも同じように考えることができる。あるウィンドウの中に項目があり、その項目を選択するとさらに別のウィンドウが開くように。 Menu.java public abstract class Menu { public abstract String getName(); public Menu add(Menu menu) { return this; } public void disp() { disp(""); }

    Composite - ゲームが作れるようになるまでがんばる日記
  • Bridge - ゲームが作れるようになるまでがんばる日記

    機能のクラス階層と実装のクラス階層を分けて、その橋渡しをする。 またゲームで考えてみる。攻撃メソッドを持った敵クラスを作成し、それを継承してゴブリンクラスを作成。 class Enemy { public: void Attack(); }; class Goblin : public Enemy { public: void Attack() { printf("Goblin Attack.\n"); } }; ここで敵クラスを継承してボス敵クラスを作成し、2回連続で攻撃する特殊攻撃のメソッドを追加した。 class BossEnemy : public Enemy { public: void SpecialAttack() { Attack(); Attack(); } }; ボス敵のゴブリンクラスを作成するため、ボス敵クラスを継承。 class BossGoblin : publi

    Bridge - ゲームが作れるようになるまでがんばる日記
  • Abstract Factory その2 - ゲームが作れるようになるまでがんばる日記

    具体的なクラスを指定せずに、インスタンスを生成することができるのがこのパターン。 例によってゲームで考えてみる。 抽象的な製品であるEnemy。 package factory; public abstract class Enemy { public abstract void Message(); } 抽象的な工場であるFactory。このgetFactoryで指定された名前のクラスを生成している。 package factory; public abstract class Factory { public static Factory getFactory(String classname) { Factory factory = null; try { factory = (Factory)Class.forName(classname).newInstance(); } cat

    Abstract Factory その2 - ゲームが作れるようになるまでがんばる日記
  • Builder - ゲームが作れるようになるまでがんばる日記

    複雑な構造を持ったインスタンスを組み上げる。 全体を構成する各パートをそれぞれ作り、それを順番に組み上げて全体を作成するというイメージかな。 では、ゲームで考えてみよう。 敵キャラが体力、大きさ、強さの3つのパラメータから出来ているとする。 class Enemy { private: int hp; int size; int power; public: void setHp(int hp) { this.hp = hp; } void setSize(int size) { this.size = size; } void setPower(int power) { this.power = power; } }; class Builder { public: void buildHp() = 0; void buildSize() = 0; void buildPower() =

    Builder - ゲームが作れるようになるまでがんばる日記
  • Prototype - ゲームが作れるようになるまでがんばる日記

    インスタンスをコピーして別のインスタンスを作り出す。 毎回、newでクラスからインスタンスを作り出すのではなく、プロトタイプとなるインスタンスをコピーして新しいインスタンスを作り出す。 ゲームで考えてみよう。ある敵が分裂するような場合があり、そのときの体力などのパラメータを同じにしたいとする。こんな場合はnewで新たに作成するよりも、コピーして作ってしまったほうが良いだろう。 class Enemy { private: int hp; public: Enemy( int inithp ) { hp = inithp; } Enemy createClone() { return new Enemy(hp); } }; void doTest() { Enemy enemy1 = new Enemy(100); Enemy enemy2 = enemy1.createClone(); }

    Prototype - ゲームが作れるようになるまでがんばる日記
    yheld
    yheld 2007/08/09
    へぇ・・・これは良い
  • Singleton - ゲームが作れるようになるまでがんばる日記

    インスタンスを1つしか作成しないようにする。 あるクラスを1個しかインスタンスを作らないように制限をかける。プログラマが1個しか作らないように注意してコーディングすればいいじゃんという話もあるが、自分ひとりでプログラムするならまだしも、複数人でプログラムを作成する場合などには誰かが誤ってインスタンスを複数作成してしまうかもしれない。こうならないようにコードでインスタンスが1個しか生成されないように制限をかける。 class Singleton { private: static Singleton singleton = new Singleton(); Singleton() { } public: static Singleton getInstance() { return singleton; } }; void doTest() { Singleton obj = Singlet

    Singleton - ゲームが作れるようになるまでがんばる日記
  • Factory Method - ゲームが作れるようになるまでがんばる日記

    Template Methodパターンをインスタンス生成に適応したもの。インスタンスを生成するメソッドを抽象クラスで定義し、具体的な生成部分は子クラスに任せる。 次の例では、TestFactory(工場)を作成し、createメソッドでTest(製品)のインスタンスを作成している。 // 製品クラス class Product { public: void exec(); }; // 工場クラス class Factory { public: Product create(String name) { Product p = createProduct(name); return p; } protected: Product createProduct(String name) = 0; }; // 具体的な製品クラス class Test : public Product { priv

    Factory Method - ゲームが作れるようになるまでがんばる日記
  • Template Method - ゲームが作れるようになるまでがんばる日記

    親クラスで枠組みを決めて、具体的な処理は子クラスで実装するもの。親クラスでテンプレートとなるメソッドを抽象メソッドで定義し、具体的な処理は子クラスで実装する。 アルゴリズム的な部分は一緒だけど、具体的な部分は異なるような場合、コピーペーストで複数のクラスを作ってしまうと、アルゴリズムのどこかに変更があった場合、すべてのクラスを修正しなくてはならない。そこで親クラスを抽象クラスとしてアルゴリズムを記述し、具体的な部分は子クラスで実装するようにすればよい。そうすれば、アルゴリズムが変更された場合は親クラスのみを修正するだけで済む。 たとえば、Read()して何らかの処理を行い、Write()するような処理があり、Read()やWrite()の対象が変わって処理が異なるような場合は次のような感じで書ける。 class Base { public: void Read() = 0; void Wr

    Template Method - ゲームが作れるようになるまでがんばる日記
    yheld
    yheld 2007/08/06
    D言語ではAbstract patternか。