ゲーム開発とデザインパターン

23
ゲゲゲゲゲゲゲゲゲゲゲゲゲゲ ~ ゲゲゲゲゲゲゲゲゲゲゲゲゲゲゲゲゲゲゲ ~ ゲゲゲゲ

Upload: takashi-komada

Post on 28-May-2015

4.634 views

Category:

Technology


1 download

DESCRIPTION

社内勉強会で使った資料を公開します。

TRANSCRIPT

Page 1: ゲーム開発とデザインパターン

ゲーム開発とデザインパターン

~コスト削減とクオリティの両立を目指して ~

もんぐり

Page 2: ゲーム開発とデザインパターン

この勉強会の目的• デザインパターンに親近感をもってもらうこと

• ゲーム開発における、よりよい設計について一緒に考えてもらうこと

• ゲームの品質と開発スピードの向上に寄与すること

ちなみに、僕はデザインパターンの専門家でもゲーム開発の専門家でもなく、どっちも駆け出しなので、暖かくご意見ご指摘ください!

Page 3: ゲーム開発とデザインパターン

デザインパターンとは• Wikipediaの定義

– 過去のソフトウェア設計者が発見し編み出した設計ノウハウを蓄積し、名前をつけ、再利用しやすいように特定の規約に従ってカタログ化したものである。

• 代表的なのは GoFの 23個のデザインパターン

• 一言で表すと「直に書かずにクラスを分けろ」ってことかなと。(個人的解釈です)

Page 4: ゲーム開発とデザインパターン

デザインパターンを学ぶメリット

• 設計の世界共通言語– 「ここは FactoryMethodで設計してるんだ」って説明すれば、「ああ FactoryMethodね」って、すぐ話が通じるよ!

• 巨人の肩に乗る• 品質向上(バグを作りこみにくい設計)• メンテナンス性向上(読みやすい、修正しやすい)

• 品質向上 開発スピード向上≒

Page 5: ゲーム開発とデザインパターン

デザインパターンを学ぶメリットデザパタ駆使したとき

クラスの独立性が高くなるようにだけ気をつけた時

直にがんがん処理を書いてる時

パフォーマンス ◯ ◯ ◯

可読性 △ ◯ ☓

クラス独立性 ◯ △ ☓

ソースを書く速度 △ △ ◯

バグ発生率の低さ ◎ ◯ ☓

トータルな開発とメンテのコストの低さ

◎ ◯ ☓

※独断と偏見に基づく評価です

Page 6: ゲーム開発とデザインパターン

23個も覚えきれないよ!

Page 7: ゲーム開発とデザインパターン

(独断と偏見で)厳選したパターンを、適用事例とともにご紹介します!

Page 8: ゲーム開発とデザインパターン

こんな経験ないですか?• このインスタンスはアプリ内で 1個だけのはずなのに、勝手に別の場所でも作られちゃった!– アプリ全体のデータを保持したクラスとかの話

• → 利用者がそれと知らずに、複数インスタンスを扱っていると、バグに気づくのが遅れると大混乱に

インスタンス 1

インスタンス 2

利用者

更新 参照インスタンス

は1個だけだよね

Page 9: ゲーム開発とデザインパターン

Singleton• 1個しか作っちゃいけないものは1個しか作れないようにしておこう

• コンストラクタで例外投げたりAssertしたり、コンストラクタをprivateにしたりして、newを禁止します。

• Cocos2d-xでは、CCTextureCacheなど、キャッシュ系でよく使われてます。CCDirectorなどの単一機能クラスも Singletonになってます。

class SingletonClass {public:

static SingletonClass* getInstance();

private:static SingletonClass* m_instance;SingletonClass();

};

Page 10: ゲーム開発とデザインパターン

こんな経験ないですか?• Animalクラスを継承した子クラスを作って、子によって違う処理はそれぞれに隠蔽するぞ!

• → 開発してるうちに、子クラスの種類がどんどん増えてきたんだが。。。• → 大量の子クラスのヘッダを#includeしちゃってるよ!  Switch-caseの caseの数がめっちゃ多いよ!

• ビルド時間増大、依存性増大、クラスの行数が増大し、扱いにくいソースに。。。

#include “Cat.h”#include “Dog.h”・・・  100個の #include#include ”Dragon.h”

bool Game::init() {m_cat1 = new Cat();m_dog1 = new Dog();・・・m_doragon1 = new Dragon();return true;

};

Page 11: ゲーム開発とデザインパターン

FactoryMethod( &AbstractFactory)• 派生クラスのどれでもインスタンス生成できるクラスを別に作っておいて、それを使うようにしよう

• 派生クラスへの依存性をなくし、ポリモーフィズムを駆使できます

class AnimalFactory {public:

IFAnimal* createAnimal(ANIMAL_TYPE type);};

IFAnimal* AnimalFactory::createAnimal(ANIMAL_TYPE type) {switch(type) {case CAT:

return new AnimalCat();case DOG:

return new AnimalDog();・・・default:

return NULL;}

}

Page 12: ゲーム開発とデザインパターン

こんな経験ないですか?• 敵によって攻撃パターン(アルゴリズム)が違う。攻撃パターンはそれぞれの敵クラスに実装しよう

• → 攻撃パターン変更依頼もらったけど、それぞれの敵クラスに処理が散らばってて、少しずつ差分があるから修正量が半端ないよ!

• → 「敵 Aの攻撃パターンを敵 Bと同じやつに差し替えといて」って依頼もらったけど、アルゴリズムに結びつけたソースにしてるからほぼ全て書きなおしだ!

Page 13: ゲーム開発とデザインパターン

Strategy• →アルゴリズムごとにクラス作って、クラス内に詳細な処理は隠蔽し、どれも同じ I/Fで使用できるようにしておこう

• 僕は、複数パターンの AIを使い分けるときによく使っています。

class AttackAIFactory {public:

IFAttackAI* createAttackAI(AI_TYPE type);};

IFAttackAI* AttackAIFactory::createAttackAI(AI_TYPE type) {switch(type) {case VERTICAL_LASER:

return new AttackAIVerticalLaser();・・・default:

return NULL;}

}

class IFAttackAI { virtual vector<Cell> createAttackCollisionArea() = 0;

・・・};

Page 14: ゲーム開発とデザインパターン

こんな経験ないですか?• 状態管理は enumだね。ゲームのループで呼ばれるメソッド内で Switch 文書いて、処理を分岐すればよし!

• →  case数の増大、 case内処理の増大。。。クラスの行数が増えて 3000 行を超えますた

switch(m_state) {case STATE_MOVING:

・・・break;

case STATE_ATTACKING:・・・break;

・・・case STATE_DEAD:

break;default

break;}

Page 15: ゲーム開発とデザインパターン

State• 状態ごとにクラス作って、どれも同じ I/Fで処理を起動できるようにしよう!

• 実際は、主クラスから、状態依存する処理だけを独立して切り出すのはなかなか難しい印象。使えるところに使っていこう。

class PlayerStateFactory {public:

IFPlayerState* createPlayerState(PLAYER_STATE state);};

IFPlayerState* PlayerStateFactory::createAttackAI(PLAYER_STATE state) {switch(state) {case PLAYER_STATE_POISON:

return new PlayerStatePoison();・・・default:

return NULL;}

}

class IFPlayerState {virtual void moveTo(Point point) = 0;・・・

};

Page 16: ゲーム開発とデザインパターン

こんな経験ないですか?• 弾幕シューティング、弾発射時にインスタンス生成、画面外にいったらインスタンス解放だ!

• →弾が多くなるとめっちゃフレームレート落ちるんですが。。。

Page 17: ゲーム開発とデザインパターン

Flyweight

• →必要なくなったインスタンスを解放せずに再利用すべし

• オブジェクトをプーリングするってことです• Cocos2d-xの場合は CCTextureCacheとか

CCSpriteBatchNodeとかの仕組みは揃ってるけど、まああんまり生成解放が頻繁だったら最初からプーリング書いてもいいと思う

• サンプルコードは書くのが面倒くさいので省略

Page 18: ゲーム開発とデザインパターン

こんな経験ないですか?• Playerと Enemyと Stageクラスを作ったぞ!

• 3者が密接に絡みすぎて、何か一つ修正するだけで影響範囲調査がしんどい。。。

Player

Enemy1

Stage

Enemy2

Page 19: ゲーム開発とデザインパターン

Mediator• →各オブジェクトを仲介するクラスを用意し、独立なオブ

ジェクト同士は直接やりとりしないようにする

• Mediatorは、次回に紹介するObserverパターンと組み合わせて、非同期処理の命令を実装するといいです– 非同期処理の例:

• 命令 :メソッド• 結果通知 : 次で紹介するObserverパターンによる通知

PlayerEnemy Stage

GameManager

Page 20: ゲーム開発とデザインパターン

(デザパタって)本当にゲーム開発の現場で

役に立つんかいな?

Page 21: ゲーム開発とデザインパターン

知り合いに聞いてみた

※このスライドは、個人情報が入ってくるので、SlideShare 版では記載を外しました。

• 個人的には、経験上、取捨選択すればおおいに使えると思っています。

Page 22: ゲーム開発とデザインパターン

まとめ• デザインパターンをいい感じに使えるようになって開発スピードと品質を向上させよう!– Singleton– FactoryMethod– State– Strategy– Flyweight– Mediator

• 次回は ObserverとMVCパターンを議論します。

Page 23: ゲーム開発とデザインパターン

参考書籍• 検索するとわかりやすい解説サイトが出てくるのでそれで

十分かもです。

• オブジェクト指向における再利用のためのデザインパターン– いわゆるGoF 本

• リファクタリング Martin Fowler 著

上の 2 冊は僕は読んでません!

• Java言語で学ぶデザインパターン• Java言語で学ぶリファクタリング入門

– 結城浩さんの本です