OOとゲームプログラミング
■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。
01/11/07 23:55ID:HnYWCQK1行うことが出来るのか語り合うスレです。
0195名無しさん@お腹いっぱい。
01/11/11 23:19ID:???では、そのIsKindOf(RUNTIME_CLASS())(のようなもの)であるとか、
Updateのメソッド自体に更新の判断をさせるほうが良い気がするのですが…。
それではデメリットがあるのですか?
0196名無しさん@お腹いっぱい。
01/11/11 23:23ID:+Lh2D+yiIsKindOfを実装するには、これまたクラスごとに面倒なコーディングが増えるわけよ。
関数を作って、SetTask(Function)を呼び出すだけとい
お手軽さとは雲泥の差があるわけ。
Updateに判断させる場合、すべてのクラスにその判断処理を実装する必要があるわけでしょ?
それまた面倒でパフォーマンスも悪いわけ。
0197187
01/11/11 23:29ID:+Lh2D+yiCTaskManager{
public:
TASK* SetTask(void* function_ptr);
void Update();
private:
TASK mTask[MAX_TASK];
};
CEnemy{
public:
static void Enemy1(TASK*);
static void Enemy2(TASK*);
static void Enemy3(TASK*);
};
0198_
01/11/11 23:34ID:Tn36jYF+俺もC++の可読性については、ちょっと同意かなあ。
ちらっと読んでもわからないんだよね、他人のソースが。
継承ツリーの根元にあるメンバなんか、いきなり出されても
作った本人しかわからないよねえ。
グローバル変数使いまくりのCでも、そっちの方が読みやすいというのはあるよねえ。
0199名無しさん@お腹いっぱい。
01/11/11 23:34ID:???特に多人数での開発になると顕著だと思うんだけど。
他のプログラマによる不正な操作を制限しやすいのはかなりメリットだと思う。
Cでもキチンと書けば問題無いんだけど、
なんか致命的かつ再現率の低いバグが出やすい気がする。
↑これは自分がへぼいのは自覚してます。
あとまともに動けば例外処理もかなり強力だと思うざんす。
0200199
01/11/11 23:36ID:???0201名無しさん@お腹いっぱい。
01/11/11 23:36ID:???>Updateに判断させる場合、すべてのクラスにその判断処理を実装する必要があるわけでしょ?
こういう場合、むしろ管理する側がチェックするよりも自分自身が判断する方が
むしろ軽くできそうなすみそうな気がしますけど…(適当でスマソ)
#もちろんこの程度ならC++使わなくても、Cだけでも出来ますけど。
class ab
{
virtual void update(const status& a)=0;
};
class con0 : public ab
{
virtual void update(const status& a){ do_update(); } // これはいつでも更新するクラス
}
class con1 : public ab
{
virtual void update(const status& a){ if(!a->pause){ do_update(); }} // pauseしてないときだけupdate
}
...
for(vector<ab*>::iterator i=obj.begin(); i!=obj.end(); i++){(*i)->update(current_status);}
0202187
01/11/11 23:46ID:+Lh2D+yiいや、
if (pause){
for (;;){
if (task[i]->update == PauseTask){
(*task[i]->update)(&task[i]);
}
}
}else{
for (;;) (*task[i]->update)(&task[i]);
}
条件分岐をループの外に持っていけるし、妙な引数も必要ない分、
圧倒的に有利だよ。
まあPauseの用途に限定するならタスク構造体に属性を持たしておいた方が便利だけど。
0203名無しさん@お腹いっぱい。
01/11/11 23:47ID:???なんとなく同意です。
自分自身のヘボさを知るものとしてはCよりもデータへの不正な制限を掛けやすい
C++の方がいいかなぁ…と思ってます。
0204名無しさん@お腹いっぱい。
01/11/11 23:50ID:???俺も楽だと思うよ。
問題が局所化されるから見る範囲がかなり限定されてくる。
まー、何にせよ慣れでしょうね。
Cべったりな人たちには無理せず使い慣れたCがよござんしょ。
0205192
01/11/12 00:00ID:???ツールではバリバリ使うんで業界的に(というか、うちの会社的に)
「これから」っていうわけでもないんですけどね。なんでツールで
使うかといえば、クラスライブラリが用意されてたりして「圧倒的
に効率が上がる」から。
ツールとか実用ソフトの場合、インターフェイスの統一性
が重要ですが、ゲームの場合は寧ろゲーム毎の独自性や面白さ
の方が優先されるわけで、その辺も難しいですね。
あと、コンシューマーの場合リソースの管理をかなり見通しが
効くようにしておかないといけないのが、楽に組めない要因で
すね。快適にプレイさせる為には必要になった時にリソース
確保じゃ遅い(先読み対応)とか・・・
メモリも、「メモリ128MB以上推奨」で済まないし、
「最悪仮想記憶で・・・」というわけにもいかない。
C++でやるにしても、メモリ管理は全部自前でしょうね。
まぁこれは、PCでもそうなんでしょうけど。
なんか、愚痴っぽいな。
0206名無しさん@お腹いっぱい。
01/11/12 00:01ID:???う〜ん、このあたりは判断すべき条件の場合分けの数であるとか、どこの
オブジェクトがその判断に責任を持つかっていう所で実装を分けるかも
しれないっすね。(そういう意味ではpauseは不適当だったか?)
私が>>202のようなソースを見たときに一番危惧するのは、条件分けが
多岐にわたったときに(pauseだけではなく、アドバタイズであるとか、
デバッグ用のモード(?)であるとか)updateの呼び出しが多個所になって
しまい、たとえばupdateメソッドの呼び出し方が変わった場合、変更が多岐
にわたってしまうんでないかい?とか思ってしまうのです。
#このあたりの考え方は好みに近いところだと思うので、なにが正解とも
#思いませんけど…。
0207名無しさん@お腹いっぱい。
01/11/12 00:44ID:tWtzB3UrCTaskManager::Update()
{
switch(mode){
case UPDAETMODE_DEFAULT:
for (;;) (*task[i]->update)(&task[i]);
break;
case UPDATEMODE_PAUSE:
for (;;) (*task[i]->update)(&task[i]);
break;
case UPDATEMODE_DEBUG:
for (;;) (*task[i]->update)(&task[i]);
break;
}
}
多岐にわたる理由などありませんが。
0208名無しさん@お腹いっぱい。
01/11/12 00:45ID:???ヲイヲイ・・・
0209名無しさん@お腹いっぱい。
01/11/12 00:46ID:tWtzB3Ur何か問題でも?
0210206
01/11/12 01:07ID:???208の煽りは私ではないですよ〜。誤解しないでね。(ニコ
#以下は好みの話し程度に読んでください。
いや、>>202のpauseの時にその呼び出し側に関係ない処理は(OOP抜きとは関係ないですけど)
呼び出し側で制御すべきでないと思うんですよ。(それは例え>>207のような形であっても、結局
caseの数だけupdateメソッドを呼び出す個所が出来るわけで。)
もし一つ一つのオブジェクトで処理を判断するのが重いぜ、やってられないぜというのであれば、
// >>201からのつづきと考えてくださいね
// 文法的に嘘があっても無視の方向で(自虐藁
class ab_collection
{
vector<ab*> abc;
void add_ab(ab* _o){ abc.push_back(_o); }
virtual void update(const status& _stat) = 0;
};
// 見たいな形でオブジェクトをまとめるクラスを一段「かませ」て、
class free_ab_collection : public ab_collection // 判断のひつようなしクラス
{
virtual void update(const status& _stat){
for(vector<ab*>::iterator i=abc.begin(); i!=abc.end(); i++){ (*i)->update(_stat); }
}
class test_ab_collection : public ab_collection // pauseフラグをチェック
{
virtual void update(const status _stat){
if(stat->pause){ return; } // ここでチェックすることで、以下のabの各クラスではチェックする必要が無くなる
for(vector<ab*>::iterator i=abc.begin(); i!=abc.end(); i++){ (*i)->update(_stat);
}
みたいにしてやれば、見通しも良いまま、効率を保つことも可能ではないかと。
(親クラスはab_collectionの塊を持ってupdateを呼び出すだけ。)
実際にプログラムで重いところって大量のメモリのキャッシュミスと回数の非常に多い単純計算
だと思ってるんで、そこさえ気をつければ、見通しよくプログラムするためのコストって許されるんじゃ
ないかと思ってます。
#もちろん、見易さは人によってそれぞれだとおもうんで、>>207さんの方法も尊重します。
0211206
01/11/12 01:09ID:???それぞれのab_collectionから継承させたオブジェクトで
>for(vector<ab*>::iterator i=abc.begin(); i!=abc.end(); i++){ (*i)->update(_stat); }
を呼ぶのは愚の骨頂ですね。ab_collectionに置くべき処理でした。
失礼…。
0212名無しさん@お腹いっぱい。
01/11/12 03:36ID:???C++を利用したことによるオーバーヘッドはほとんど
気にしなくていいような気がします。
0213名無しさん@お腹いっぱい。
01/11/12 07:13ID:???0214名無しさん@お腹いっぱい。
01/11/12 07:56ID:???CTaskの継承クラスのサイズに最大128バイトとか制限かけて、
メモリプールから確保するようにする。
0215名無しさん@お腹いっぱい。
01/11/12 21:17ID:???オーバーライドだと思うが…。
細かい突っ込みかな。
malloc自体が仮想メモリを利用することが前提の関数だし、おそらくnewもそうだろうと思います。
仮想メモリがある環境だと、あまりメモリの分断化は気にしないかも。
コンシューマだとガベージコレクトやメモリコンパクションやらを考えないと
いけないでしょうね。
メモリマップを始めにきっちりと作るというのも手だと思いますけど。
0216名無しさん@お腹いっぱい。
01/11/12 21:24ID:???オーバーロードでも対処できるよ。
newに特殊なパラメータ(フラグ)を取らせてそれによって、デフォルトのnewとは
動作を変える。
この場合、newの動作が暗黙のうちに最適化されるのではなく、プログラマが必要
に応じてメモリ割り当ての方法を選択できる。
うまくやれば、こっちの方が便利かもしれないよ。
0217名無しさん@お腹いっぱい。
01/11/12 21:28ID:???メモリ領域をどうすり合わせるかで挫折した。
Cの場合は、構造体内部に関数へのポインタがあればそれを切りかえることで
簡単に実現できた。
C++の場合、上記メソッドのオーバーロードで簡単に実現できるのはひとつの
メソッドだけ。
無理やりやろうとすると、オーバーロードするメソッドの中で
処理するメソッドへのポインタを利用して処理を飛ばすという、
なんとも汚いものになった。
こんなことするくらいなら、構造体+関数へのポインタで処理させたほうがまし
だと思った。
0218名無しさん@お腹いっぱい。
01/11/12 21:36ID:???ごめん、ちょっとわかりにくい。
「オーバーロードで簡単に実現できるのは1つだけ」というのは
operator newのオーバーロードが1つだけってこと?
0219名無しさん@お腹いっぱい。
01/11/12 23:02ID:aPZmJhKt>なんとも汚いものになった。
あまり解釈に自信がないんだけど、例えばこういうの? 汚いかなあ。
typedef void(Task::*TaskFunc)();
class Task {
public:
void SetMethod(TaskFunc updateFunc) { m_updateFunc = updateFunc; }
void Update() { (this->*m_updateFunc)(); }
private:
TaskFunc m_updateFunc;
};
class HogeTask : public Task {
public:
HogeTask() {
SetFunc((TaskFunc) Func1);
}
void Func1() {
...
SetFunc((TaskFunc) Func2);
}
void Func2() { ... }
void Func3() { ... }
};
0220219
01/11/12 23:06ID:???class Task {
friend class TaskManager;
public:
void SetMethod(TaskFunc updateFunc) { m_updateFunc = updateFunc; }
private:
TaskFunc m_updateFunc;
};
0221219
01/11/12 23:07ID:???s/Method/Func/g
0222名無しさん@お腹いっぱい。
01/11/13 00:29ID:???0223名無しさん@お腹いっぱい。
01/11/13 00:30ID:???0224名無しさん@お腹いっぱい。
01/11/13 04:25ID:???C++で関数ポインタ使うのはイヤみたいに言うのかわからん。
0225名無しさん@お腹いっぱい。
01/11/13 10:18ID:???みんなUpdateですか。
0226名無しさん@お腹いっぱい。
01/11/13 13:13ID:ClbS1Bbeゲーム系だと特に期限ギリギりでの仕様変更が多いので(仕様書な
んてものが存在しない場合も多いけど)、パッチ当てる感覚でその場
がしのげて良いです。
その後の事はしらん(藁。
0227名無しさん@お腹いっぱい。
01/11/13 14:05ID:FoEbYEtaFunc1 は
typedef void (HogeTask::*FuncType)();
であって、
typedef void(Task::*TaskFunc)();
ではない。
メンバ関数へのポインタはクラスによってサイズが違うという話を聞いたんだが、
SetFunc((TaskFunc) Func1);
このキャストは安全なのか?
を
0228名無しさん@お腹いっぱい。
01/11/13 14:08ID:???マクロ使った状態マシン組みあわせてみない?
オレは今から試すにょ。
0229名無しさん@お腹いっぱい。
01/11/13 14:17ID:???安全じゃないからキャストしてると思われ(w
仕様上は安全じゃない(プログラミング言語C++第3版15.5.1)が、
C++の実装上は上手くいくのではないか。
ちとキモチワルイ感はある。
0230名無しさん@お腹いっぱい。
01/11/13 14:36ID:???エラーが出そうなものだが。
g++でコンパイルしてみたけど、駄目だった。
コンパイラの問題かな。
0231名無しさん@お腹いっぱい。
01/11/13 14:58ID:???#define DECLARE_TASK(TypeName) \
void (TypeName::*m_updateFunc)();\
public:\
virtual void Update(){(this->*m_updateFunc)();}\
private:\
#define SET_TASK_FUNC(FuncName) {m_updateFunc = FuncName;}
class Task
{
public:
virtual void Update() = 0;
};
class HogeTask : public Task
{
DECLARE_TASK(HogeTask)
public:
HogeTask(){
SET_TASK_FUNC(Func1);
}
void Func1(){
…
SET_TASK_FUNC(Func2);
}
void Func2(){};
};
0232217
01/11/13 15:31ID:4q6jfi+W219さんのソースを利用させてもらいます。
extern "C" {
#include <stdio.h>
}
//-----------------------------------------------------------
// 基本擬似タスク
//-----------------------------------------------------------
class Task {
public:
Task() {};
virtual ~Task() {};
virtual void SetFunc(void) {}
virtual void Update(void) {}
};
//-----------------------------------------------------------
// 擬似タスク定義部
//-----------------------------------------------------------
class HogeTask;
typedef void(HogeTask::*TaskFunc)(void);
class HogeTask : public Task {
public:
HogeTask() { SetFunc(&HogeTask::Func1); }
~HogeTask() {};
void SetFunc(TaskFunc updateFunc) { m_updateFunc = updateFunc; }
void Update() { (this->*m_updateFunc)(); };
void Func1() { printf("Func 1\n"); SetFunc(&HogeTask::Func2); }
void Func2() { printf("Func 2\n"); SetFunc(&HogeTask::Func3); }
void Func3() { printf("Func 3\n"); SetFunc(&HogeTask::Func1); }
private:
TaskFunc m_updateFunc;
};
0233217
01/11/13 15:32ID:4q6jfi+W//-----------------------------------------------------------
// 擬似タスク実行部
//-----------------------------------------------------------
class ExecuteTask {
Task *taskArray[100];
int iTaskPoint;
public:
ExecuteTask() { iTaskPoint = 0; }
void SetTask(Task* prtTask) { taskArray[iTaskPoint++] = prtTask; }
void execute(void) {
{for(int i = 0; i < iTaskPoint; i++) {
taskArray[i]->Update(); }
}
}
};
0234217
01/11/13 15:34ID:4q6jfi+W//-----------------------------------------------------------
// メイン
//-----------------------------------------------------------
int main(int argc, char** argv) {
HogeTask hogeTask;
HogeTask hogeTask2;
ExecuteTask executeTask;
printf("<<1st>>\n");
executeTask.SetTask(&hogeTask); // タスク1セット
executeTask.execute(); // タスク実行
printf("<<2nd>>\n");
executeTask.execute(); // タスク実行
printf("<<3rd>>\n");
executeTask.SetTask(&hogeTask2); // タスク2セット
executeTask.execute(); // タスク実行
return 0;
}
0235217
01/11/13 15:43ID:???いろいろ機能がありました。
ともあれ、結局構造体+関数へのポインタで実装したほうが
分かりやすい上に、パフォーマンスの上という理由で捨てました。
0236名無しさん@お腹いっぱい。
01/11/13 15:46ID:???VC だとメンバ関数のアドレスはその名前だけでよいが、
C++ の仕様だと &クラス名::関数名 でないとダメ
そこ以外でエラーはでないと思われ
0237230
01/11/13 20:52ID:???うむ確かに、うまくいった。
つうか、なぜ気がつかない、俺。
こうなると、219のコードが一番スマートなのかな?
キャストが嫌ってことなら、231になるか。
0238名無しさん@お腹いっぱい。
01/11/13 21:09ID:xYb3Zs4nこれをいかに楽に記述する方法を考えるかみたいなー。
何かタスク記述言語でも作って、
C/C++ソースに変換するフィルタでも用意するのがええかのう。
タスク {
タスク変数
タスクの状態
タスク作成時の処理
タスク破棄時の処理
汎用イベント処理
状態1 {
状態の初期化
更新処理
状態の後始末
汎用イベント処理
}
状態2 {
状態の初期化
更新処理
状態の後始末
汎用イベント処理
}
...
}
0239230
01/11/13 21:25ID:???って感じもするな…。
#include <iostream>
class Task;
class TaskManager;
typedef void(Task::*TaskFunc)();
class Task {
friend class TaskManager;
public:
void SetFunc(TaskFunc updateFunc) { m_updateFunc = updateFunc; }
// void Update() { (this->*m_updateFunc)(); }
private:
TaskFunc m_updateFunc;
};
class HogeTask : public Task {
public:
HogeTask() {
SetFunc(static_cast <TaskFunc> (&HogeTask::Func1));
}
void Func1() {
cout << "Func 1\n";
SetFunc(static_cast <TaskFunc> (&HogeTask::Func2));
}
void Func2() { cout << "Func 2\n"; }
void Func3() { cout << "Func 3\n"; }
};
class TaskManager {
Task *taskArray[100];
int iPoint;
public:
TaskManager() { iPoint = 0; }
~TaskManager() {}
void setTask(Task* task) { taskArray[iPoint++] = task; }
void execute(void) {
{for(int i = 0; i < iPoint; i++) {
(taskArray[i]->*(taskArray[i]->m_updateFunc))();
}}
}
};
0240名無しさん@お腹いっぱい。
01/11/13 22:00ID:???#define VX (p->vx)
みたいな真似をしたりするのもどうも気が引けるとゆーか・・・。
0241名無しさん@お腹いっぱい。
01/11/14 12:35ID:???多少高かろうが低かろうが屁みたいなもんじゃん。
描画エンジンの都合で……ならわかるけど。
0242名無しさん@お腹いっぱい。
01/11/14 12:52ID:???文句言っている人は、たぶんコストが無視できないプラットフォームで作ってるんですよ・・・。
0243名無しさん@お腹いっぱい。
01/11/14 23:11ID:???0244名無しさん@お腹いっぱい。
01/11/15 00:27ID:rnP2aOWiんなことはない。
オブジェクト指向ヲタはSetPixel,GetPixelとかまで仮想関数
にしたがるから。
それにパフォーマンスが問題にならないような上位層はスクリプトにするのが普通だし。
0245名無しさん@お腹いっぱい。
01/11/15 00:36ID:???それ描画まわりじゃねえか
0246名無しさん@お腹いっぱい。
01/11/15 01:25ID:???そういう簡単な挙動しか実装しない場合は
オブジェクト指向化の恩恵も少ないと思われ。
0247名無しさん@お腹いっぱい。
01/11/15 02:14ID:???たぶんサンプルコードだからだと思うけど、
Task *taskArray[100]; とかがいや。std::list使おうよぅ
0248名無しさん@お腹いっぱい。
01/11/15 11:09ID:???禿同。
0249名無しさん@お腹いっぱい。
01/11/15 12:18ID:uH85Rn+sなんで?
パフォーマンスのため?
タスクシステムを忠実にC++で再現したいから?
CSomeTask::update ()
{
switch(this->mode){
case UPDAETMODE_DEFAULT:
this->do_default ();
break;
case UPDATEMODE_PAUSE:
this->do_pause ();
break;
case UPDATEMODE_DEBUG:
this->do_debug ();
break;
}
}
実際これでほぼ十分でしょ。
0250名無しさん@お腹いっぱい。
01/11/15 12:36ID:???>タスクシステムを忠実にC++で再現したいから?
それに加えて、激しく状態遷移するタスクのデバッグは
もうこりごりってのもあるです。
0251名無しさん@お腹いっぱい。
01/11/15 13:55ID:???ゲーム全体で擬似的なスレッド処理を実現させたいからだと思われ。
背景をスクロールさせながら、ウィンドウをアニメショーンさせつつ移動させたり
するのをスレッドで実装すると分かりやすいからでしょう。
普通に、ループのなかでやるとifの連発になりそうだし。
>std::list使おうよぅ
STLを使うとついてこれない人がいるから…。
という冗談はさておき、サンプルだからでしょう。
0252名無しさん@お腹いっぱい。
01/11/15 14:27ID:???0253名無しさん@お腹いっぱい。
01/11/15 15:05ID:???汎用性の問題。
関数ポインタの場合はswitchと違って、
機能を増やしても書き直す必要がない。
0254名無しさん@お腹いっぱい。
01/11/15 17:07ID:???C++のメンバ関数へのポインタでやると
関数1つ追加ごとにヘッダーへの変更が発生するのも問題。
privateな関数をどうしてヘッダーに書かねばならん!
0255名無しさん@お腹いっぱい。
01/11/15 17:56ID:???listは遅いのでvector使おう。
0256名無しさん@お腹いっぱい。
01/11/15 19:27ID:???オブジェクト志向っぽくない気がする。
0257名無しさん@お腹いっぱい。
01/11/16 00:18ID:RSv3E/5DC++は、クラス定義を見ただけで、だいたい何をやってるか分かって
便利だと思っていた俺は厨なのかしらん。
っていうか、みんなVC++のClassViewを使いませんか?
0258名無しさん@お腹いっぱい。
01/11/16 00:30ID:???何言ってるのよ
市販品かいとりますがな
0259名無しさん@お腹いっぱい。
01/11/16 00:31ID:qXQUQt+7MFCに不満が山ほどあるから、使ってない。
0260名無しさん@お腹いっぱい。
01/11/16 00:42ID:???あのコードだとタスクは死なないみたいだけど、
ふつー死ぬでしょ 順番かんけーなく
eraseのコスト考えたらlist
0261名無しさん@お腹いっぱい。
01/11/16 00:47ID:???>>259
SDKベースでもClassViewは使えるよ。コード補完も。
0262名無しさん@お腹いっぱい。
01/11/16 00:59ID:???あ、ClassViewか
スマソ、ClassWizardと勘違い
0263名無しさん@お腹いっぱい。
01/11/16 01:54ID:???enum{
WORK1,
WORK2,
WORK_MAX,
};
DWORD Work[WORK_MAX];
をグローバルで宣言して共用してます。
もっとスマートで近代的なやり方を教えてプリーズ。
OOと関係無い可能性があるので、sage
0264名無しさん@お腹いっぱい。
01/11/16 03:09ID:???0265254
01/11/16 06:16ID:???べつにヘッダーに書く手間が面倒なわけじゃない。
外部が使用するインターフェースに変更があるわけじゃないのに
内部に機能を追加するだけで、インターフェースを使用している
モジュールに再コンパイルがかかるのが嫌なだけ。
0266254
01/11/16 06:21ID:???0267名無しさん@お腹いっぱい。
01/11/16 15:25ID:???0268254
01/11/16 15:58ID:???まぁそのくらいはどうでもいいが、いちいち基底クラス作って
どうたらこうたらなんてやってられんと思うのだが…
0269名無しさん@お腹いっぱい。
01/11/16 18:20ID:???VC++使ってると全然気にならないんだけどな。
0270名無しさん@お腹いっぱい。
01/11/16 23:37ID:???0271名無しさん@お腹いっぱい。
01/11/17 00:32ID:9iW0SS+5こーゆー書き方なら、たまぁにする。
class CMain;
class CSub
{
public:
CSub(){}
virtual ~CSub(){}
virtual void FunkA(CMain*pMain) = 0;
virtual void FunkB(CMain*pMain) = 0;
};
class CSubNull : public CSub
{
public:
void FunkA(CMain*){}
void FunkB(CMain*){}
};
class CMain
{
CSub*m_pSub;
static CSubNull m_SubNull;
public:
CMain(){ m_pSub = &m_SubNull; }
virtual ~CMain(){}
void FunkA(){ m_pSub -> FunkA(this); }
void FunkB(){ m_pSub -> FunkB(this); }
void SetSub(CSub*pSub)
{
if(pSub == NULL)pSub = &m_SubNull;
m_pSub = pSub;
}
CSub*GetSub(){ return m_pSub; }
};
0272名無しさん@お腹いっぱい。
01/11/17 00:51ID:???0273名無しさん@お腹いっぱい。
01/11/17 13:55ID:???デザインパターン勉強すれば便利に使えるんだけど、使えるかどうか試してみるだけの人にデザパタ勉強しろとは言えないからなぁ。
0274名無しさん@お腹いっぱい。
01/11/17 18:20ID:???ボトルネックとか、無駄な継承等を最適化していったら、どっかで既に使われていたパターンの
亜流だったなんての事は、実際かなりあったよ・・・
0275名無しさん@お腹いっぱい。
01/11/17 19:25ID:???意味不明
0276名無しさん@お腹いっぱい。
01/11/18 02:39ID:???デザパタの学習をやり出せば解る。
デザパタはOOを十分理解してる事が前提で話を進めてるので。
0277ラム
01/11/18 09:59ID:m/JYi1e10278名無しさん@お腹いっぱい。
01/11/18 10:48ID:???違う、そういう意味じゃない。デザインパターンまで実務に使ってる。
キミの言ってることのつながりが全然わからないと言っている。
0279名無しさん@お腹いっぱい。
01/11/18 20:54ID:???0280名無しさん@お腹いっぱい。
01/11/18 21:18ID:???つかっててあたりまえだといいたいんだろう? >>279
0281名無しさん@お腹いっぱい。
01/11/18 22:29ID:???http://www.totempole.net/patterns/gamepatterns.html
こんな試みもあるがね。
0282名無しさん@お腹いっぱい。
01/11/19 22:42ID:???カードゲームを作ろうとしたときカード1枚1枚をクラスとして扱う?
カードの枚数だけクラスが出来るんかな…
0283名無しさん@お腹いっぱい。
01/11/19 23:38ID:???MT:G 系のカードごとにルールがあるカードゲーム?
カードクラスとルールクラスで構成するか、それぞれをクラスにするかだね。
Prototype や Flyweight パターンを参照してみて。
↓だけじゃ分からないと思うけど、参考までに。
http://www.ff.iij4u.or.jp/~ahirusan/Java/patterns/prototype.html
http://www.ff.iij4u.or.jp/~ahirusan/Java/patterns/flyweight.html
0284名無しさん@お腹いっぱい。
01/11/20 00:08ID:???Flyweight パターンが近そうなので
もうちょっと勉強してみます。
0285名無しさん@お腹いっぱい。
01/11/20 20:34ID:???オブジェクト志向してたんじゃないだろうか。
基底クラス武将を継承するプレイヤー武将クラス、大名武将クラス、一般武将クラス。
それらのオブジェクトが家臣団ツリー構造で管理され、
マルチスレッド処理で並列で動いてる。
当時これをつくったひとは本当に天才だとおもう。
ずっと後に出た、これと似たシステムのガンパレードマーチはさんざん自慢しまくってたが。
0286名無しさん@お腹いっぱい。
01/11/20 21:25ID:???本に出てるのは他人に教えても良いゴミテクと知れや。
0287名無しさん@お腹いっぱい。
01/11/20 23:36ID:2YNiudBT例えば、ゲームボーイとか、タイトなパフォーマンスが要求されるとことか、
まぁあったでしょうけど、やっぱ今後は開発効率の向上が必須項目。
例えば、全部組み込みJavaでゲームが書かれるようなことにも数年後にはなり
かねないしさ。
>101
モジュールやデータ構想の勉強っって何ですか?
0288名無しさん@お腹いっぱい。
01/11/20 23:43ID:???アマですか>287
0289名無しさん@お腹いっぱい。
01/11/21 07:35ID:???こういうやつよくいるわ。
0290名無しさん@お腹いっぱい。
01/11/21 11:44ID:kTxoHJqc理解してないのは分かるわねー。
0291名無しさん@お腹いっぱい。
01/11/21 12:33ID:???開発効率のほうが今後のネックだと思うが。
納期に追われたこと無いの?>288
0292名無しさん@お腹いっぱい。
01/11/21 17:02ID:???+→シーン+→キャラクタ→モーション
+→キャラクタ→モーション
なんて風にオブジェクトを階層構造にしてるとき
キャラクタの描画メッセージは、どいつがどのように送りますか?
それとも、こんな構造にはしませんか。
0293名無しさん@お腹いっぱい。
01/11/21 20:28ID:7vVUdWJ9確かにデザパタ厨房は、
今は物理シミュレーションの時代だとか言ってるゲーハー厨並に痛いけど
(そんなのファミコン時代からやってるって…)
デザインパターン自体には、
昔からの手法に共通の名前を与えるという意義はあると思う。
0294名無しさん@お腹いっぱい。
01/11/21 20:52ID:BPHGewxMプログラマ間の意思疎通がシャア並みに速くなる。
■ このスレッドは過去ログ倉庫に格納されています