OOとゲームプログラミング
■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。
01/11/07 23:55ID:HnYWCQK1行うことが出来るのか語り合うスレです。
0444名前は開発中のものです。
02/01/10 04:58ID:???0445名前は開発中のものです。
02/01/10 05:05ID:PNlj8pol熟練者ですか?(自分が経験激浅)
ぶっちゃけた話、どういう構造がベストなんですかね?
今のメイン組んでる人は、あるシーン用素材を元に、
必要なオブジェクトをどんどんnewしていって、
ヒープへのポインタをオブジェを管理するクラスが持つvectorに
pushしてく。
アニメーション関係はコンテナ化されています。
プリミティブ、モデル等はベースクラスから派生してて、
Render等のvirtual関数でそれぞれのCpu処理,描画処理をする。
て感じです。
難点は、殆どの処理が自動化されてて、テスト的な処理をしたくても、
シーンの素材ファイルを読まないと何も出来ない。
シーンはストリームで読み込んでて、手動で自分が作ったオブジェクトを
作る時等、初期化手続きが凄い面倒。等
STLはlist,vectorぐらいしかつかってないなあ。
0446名前は開発中のものです。
02/01/10 05:08ID:???0447名前は開発中のものです。
02/01/10 05:09ID:???0448名前は開発中のものです。
02/01/10 07:55ID:???「OOP=即座に開発効率が上がると思い込む」
というのがあるのだけど。
OOPはその前に痛みを伴う。初期の設計に欠点があれば
設計が見なおされるまでその禍根は残る。
設計が完璧になればその再利用性は飛躍的に向上するけど
問題はそのコストを支払い、堪えられるかということ。
それでもかまわないという男気あふれる者にこそOOPは
ふさわしい。
(Template Method で実装を切り離せば良いって
いう話ではなくて、より構造的な問題。)
0449名前は開発中のものです。
02/01/10 08:21ID:???0450名前は開発中のものです。
02/01/10 12:44ID:FBG0h4RwModern C++ design/アンドレイ・アレキサンドレスク
今この本を注文しているんだけど、変態っぽくてなかなか良いらしいぞ。
0451名前は開発中のものです。
02/01/13 22:14ID:UnhLMzSAだから、べつにOOが良いか悪いかとか言う必要も無いと思う今日この頃。
0452名前は開発中のものです。
02/01/13 23:45ID:???0453名前は開発中のものです。
02/01/14 19:49ID:f6dWfBQb単純にオブジェクトの寿命と接続の関係が整理されるだけでも、
確実にプログラムの堅牢さも作業効率も上がる。
職業プログラマは大抵経験則的にそれを分かってるし、OOP言語を用いなくとも
自前のルールでそれを実装してすらいる。
通常、OOP的アプローチが足を引っ張る状況の全ては「学習不足」に起因する。
ただ、実際の開発行為は、ほとんどの場合常に自身の学習不足と向き合わなければならないわけで…。
既に分かりきったハードで慣れ親しんだ機能を実装する「答えが見えてる」場合はともかく、
学習を伴う開発行為(出たばっかの新ハードを扱うとか)で、アプローチの仕方がわかんにゃい場合、
出だしがやたら遅くなったり、一日紙の上だけで悶々としたり、傍から見てると遊んでるようにしか
(本人苦しんでても)見えないという罠や、最初のアプローチの仕方を間違えると、その遺恨を
いつまでたっても残してしまうという罠も。
>>445
STL は俺も普段は vector と list だけだ。
ツール類なら、string iostream なんかにも出番が回ってくる。
一時期 map も使ってたが、この連想マップがベタな比較コードに勝る
速度を出したことが(経験上)ないので、最近は出番なし。
0454名前は開発中のものです。
02/01/14 19:53ID:???話はそれからだ。
0455名前は開発中のものです。
02/01/14 20:23ID:???罠んところ読んでると泣けてきた。
0456名前は開発中のものです。
02/01/14 20:26ID:???GCのふん詰まりを恐れて
オブジェクトがnewできない&クラス分けできない罠に陥ります。
0457名前は開発中のものです。
02/01/14 23:13ID:???インクリメンタルGCと言うものがあるのだよ
0458名前は開発中のものです。
02/01/15 00:03ID:???なんだよそれ。参照カウンタGCのこと?
0459名前は開発中のものです。
02/01/15 09:02ID:???ちょっとづつ断続的にGCしていくやつのことでは。
まとめてGCするのと違って長時間のふん詰まりがない
0460名前は開発中のものです。
02/01/15 16:48ID:???0461445
02/01/16 01:57ID:???考えてみたんですが、やっぱり、関数ポインタ+(実体)ワークでないと駄目な気がする。
理由としては、
関数の切り替えがクラスのポインタだと、別途newしておく必要がある。
てことは、100個のタスクの中身が、全部A、全部Bという状況だと、
A,Bともに100個ずつクラスをnewする必要がある。
て所で詰まりました。
俺の知らない良い、解決方法があるんですかね?やっぱ。
0462名前は開発中のものです。
02/01/16 02:20ID:???デザインパターンマンセー的にはflyweightパターンが適用できると思われ
0463名前は開発中のものです。
02/01/16 02:22ID:???0464445
02/01/16 03:08ID:???デザパタはまだ調べてないです。
どういったものなんでしょうか?部分的にでも教えてくだせい。
>>463
それって、OKなんですかね?CPU負荷とか。
自分はやったことがないです。(ゲーム中にnew/delete)
0465名前は開発中のものです。
02/01/16 03:12ID:???それならメンバー関数を関数ポインタを登録しようよ・・・。
つか、Aクラス、Bクラスをメンバに持つCクラスを作って
Cクラスで切り替え管理とか。そゆいみじゃない?
詳しくは割愛するけど、テンプレートを利用するとCに戻れな
くなるぐらい完璧なタスク処理が実現できるよー。
0466名前は開発中のものです。
02/01/16 04:10ID:???それ今うちで作っているライブラリの仕様と全く同じだよ。
その難点はそういう仕様がそのライブラリに無いのが原因だから、
つけてもらえばよいさ。
0467445
02/01/16 04:34ID:???>Cクラスで切り替え管理とか。
うーん、具体的には、どうやって切り替えをするのかわからないです。
テンプレートですか、、。
あれって、大雑把に言うと、引数の型チェックしてくれるマクロ関数
ですよね?
taskクラスをテンプレートで作って、taskが使用するリソース
(GraphAPI,SoundAPI,,,等)クラスを引数で渡す。て感じですかね?
ヒント下さい。
>>466
そうすか、、。
ウチは、安くてプラグイン書きやすい3Dツールで吐き出すのを
前提にしたライブラリだと思います。多分
0468名前は開発中のものです。
02/01/16 04:49ID:???A)優先順位をつけて、処理を割り振る機構
と
B)処理を割り振られた方が状態を遷移させながら仕事をこなす
のと二つがセットなんですね。
私は、A)だけがタスク処理だと思っていた。
0469名前は開発中のものです。
02/01/16 05:00ID:???状態を整数で持っていて、switch文で切り換えていたね。
#全然、オブジェクト指向じゃないな。
0470名前は開発中のものです。
02/01/16 05:01ID:???うんと、テンプレートの方はとりあえず忘れて。きちんと理解
できた時に必然的に解るとおもう。
で、下のモデルみたいな感じにすればいいとおもうんだけど。
taskC
{
public:
void changeA(){ pTask = &m_TA; }
void changeB(){ pTask = &m_TB; }
private:
void Exec(){ pTask->Exec(); }
task* pTask;
taskA m_TA;
taskB m_TB;
}
まぁ、これでもいーんだけど
void Exec(){
switch(m_Mode){
case 0: m_TaskA.Exec();break;
case 1: m_TaskB.Exec();break;
}
0471名前は開発中のものです。
02/01/16 05:19ID:???一つの抽象クラス(A)を継承して、関数に相当するクラスを書く。
一つの抽象クラス(B)を継承して、実体ワークに相当するクラスを書く。
Aに、Bへのポインタを引数にとるapply()関数を実装。
Bに、Aへのポインタとexecute()関数と、change_state()関数を実装。
# あっ、ややこしいね。確かに。
0472名前は開発中のものです。
02/01/16 05:23ID:???楽なのか。
#おすすめしないけど。
0473名前は開発中のものです。
02/01/16 06:36ID:???スレの最初のほうをご覧ありたし。
0474名前は開発中のものです。
02/01/16 07:59ID:08gPS5TMインターフェイスクラスを多重継承して、
自前の仮想関数テーブルへのアドレスを上書きする。
C++の仮想関数と、Cの関数ポインタをオーバーヘッドなしに両立できる。
0475名前は開発中のものです。
02/01/16 13:04ID:???0476名前は開発中のものです。
02/01/16 21:30ID:???メンバ関数ポインタを使えばいいだけ、という気がするが。
0477名前は開発中のものです。
02/01/16 21:43ID:???実装継承が絡んだ場合、this にオフセットをかまし忘れて死にそうな予感。
0478名前は開発中のものです。
02/01/16 22:13ID:Hxpiv8sA関数呼び出し方法はあくまで、C++的にしたいんですわ。
メンバ関数ポインタコールをインライン関数でラップする方法もあるけど、
仮想関数としてはつかえんでしょ。
>>477
だから多重継承を使うの。
最初の4バイトは実装継承用の仮想関数テーブルアドレス、
次の4バイトにオーバーライドするアドレスをマッピングする。
スーパークラスの仮想関数の数に影響されずに上書きできる。
0479名前は開発中のものです。
02/01/16 22:28ID:???仮想関数へのポインタを取ることは可能だけど、そういう話じゃなくて?
実装継承の話は、
class Deriv : public A, public B
{};
と定義されていた場合、Deriv 経由で B のメソッドを呼び出すときにはメソッドに渡す this ポインタは
Deriv::this では NG だって話と思われ。コンパイラの実装によるけど、たとえば Deriv に A, B のサブ
オブジェクトが順番に並んでる場合には
reinterpret_cast<char*>(Deriv::this) + sizeof(A)
を this として渡す必要があるよね。
0480名前は開発中のものです。
02/01/16 22:33ID:Hxpiv8sAまあコンパイラの実装依存ですが、
class Deriv : public A, public B
{
int a;
};
の場合、
virtual table address A
virtual table address B
int a
とマッピングされるので、
virtual table address B
の部分を独自の関数テーブルへのアドレスに書き換えてやれば可能かと。
Bのインターフェイスを渡すときは、
this + 4とされているので、Aのサイズに依存はしないはず。
0481名前は開発中のものです。
02/01/16 23:21ID:???ハックくせー…つうか、明らかにC++の言語仕様上でやる意味ないぞ?そんなの。
単にシンボル解決の問題みたいだし、やはり>>476が順当だろう。
スレの主旨的には邪道の極みだと思うが、どーさ。
煽るつもりじゃないのでsage
0482名前は開発中のものです。
02/01/16 23:24ID:???趣味でやるなら止めないが、仕事でそんなコード出してきたら肩を叩かせていただく、ってところだな。
ま、コンパイラの吐くコードを探りつつ、いろいろやるのは面白いことは面白いよな。
参考文献
Inside the C++ Object Model
0483481
02/01/16 23:48ID:Hxpiv8sAゲームプログラムでは必須のテクだと思うぞ。
関数ポインタの使い勝手と、C++の便利さの両方を享受できる
画期的な手法。
もし移植性を高めたいなら、
仮想関数テーブルのアドレスをインスタンスメモリ内から検索してやればいい。
class B;
int adr = *((int*)&B);
int* src = ((int*)this);
for (int i=0;i<sizeof(this_class);i++){
if (adr == src[i]) src[i] = overwride_address;
}
0484名前は開発中のものです。
02/01/16 23:55ID:???不満の無いタスクシステムは完成しているのだが、どーも、生成
時の記述だけ異常に複雑になるんだよなー。
なんかよさげな方法で実装している人いる?
0485名前は開発中のものです。
02/01/16 23:58ID:???画期的っていうかswitch分で処理分岐するのじゃダメなの?
コンパイラのコード的には似たようなもんだと思うけど。
0486名前は開発中のものです。
02/01/17 00:02ID:???まぁ、人間たまに「俺は天才なんじゃないか」って思うことがあるから、落ち着くまではそのままに
しておいてあげるのが良いかと。
0487名前は開発中のものです。
02/01/17 00:04ID:BamJYCnxswitch分岐はオーバーヘッドが大きいでしょ。
1、ステートのフェッチ、
2、範囲チェック×2、
3、ジャンプテーブルのフェッチ、
4、ジャンプ
仮想関数テーブルのオーバーライドなら、
コストは仮想関数を直接呼び出すのと変わらない。
コンパイラのコード的には別物です。
0488名前は開発中のものです。
02/01/17 00:08ID:BamJYCnxおいおい、折角貴重なノウハウを享受してやっているのに。
お前もちょっとは有益なことを書き込めよ。
0489485
02/01/17 00:21ID:???つか、ワークシステムにおいてそのオーバヘッドがどれぐらいの
ネックになるのん?1Sync内に1000個もワークは生成しない
しょ?まぁ技術論的には面白いが。
0490名前は開発中のものです。
02/01/17 00:30ID:???default文の無いswitchは単純なJumpTableにコンパイルされるけど。
0491名前は開発中のものです。
02/01/17 00:32ID:BamJYCnxまあワークシステムのUpdate程度の用途であれば
オーバーヘッドの差は微々たる物でしょうね。
どちらかというと、new/deleteなしに、
Stateパターンを適応するのが本来の目的なのです。
0492名前は開発中のものです。
02/01/17 00:35ID:???前にも誰か書いてたが、なぜ関数ポインタを使わないんだ? C++ だと仮想関数へのポインタも取得
できるから、それで何ら問題ないと思うんだが。
0493名前は開発中のものです。
02/01/17 00:38ID:BamJYCnxそれは有り得ません。
なぜなら、例えdefaultがなくとも、
変数が必ずcase内の値を取ることが保証されない限り
範囲チェックは必須だからです。
switch(a){
case 0:break;
case 1:break;
};
という構文において、aが0と1の値以外を取らないことは、
静的に保証できません。
まあ、
switch(a&1){}
とすれば最近の最適化コンパイラならdefaultを省略してくれるかもしれませんが。
0494名前は開発中のものです。
02/01/17 00:41ID:???ハイハイ。PS2だかPCは偉いね。
0495名前は開発中のものです。
02/01/17 00:43ID:BamJYCnx外部からクラスメンバを呼び出すとき、
unknown->Method()
としたいからです。
0497名前は開発中のものです。
02/01/17 01:10ID:???それは、単純な転送関数を書けば良い気がするけど。たとえば、下のようなコードと比較して得失は
何なんでしょ?
> 仮想関数としてはつかえんでしょ。
これなのかなぁ。
struct State
{
void exec1() {}
void exec2() {}
};
class Foo
: private State
{
void (Foo::*pMethod)();
public:
Foo() : pMethod(&State::exec1) {}
void method() { (this->*pMethod)(); }
};
int
main(void)
{
Foo foo;
foo.method();
return 0;
}
0498名前は開発中のものです。
02/01/17 01:20ID:iYo4faYamethodを仮想関数にすると、インライン展開できないので、
関数コール分のオーバーヘッドが増える。
この両者を解決するのが仮想関数テーブルアドレスの上書きであるということ。
0499名前は開発中のものです。
02/01/17 01:33ID:???0500名前は開発中のものです。
02/01/17 02:08ID:jIMgxZOU直接vtable書き換えるようなオバカな真似してどうするのさ。
それはコンパイラ提供側の仕様に依存しているという最悪の選択肢。
正直、仮想関数のオーバーヘッドが気になるレベルの性能が必要なら、
もっと別の解決法を考えた方がいい。
仮想関数の機構は、基底を同じくするクラスの多態性を実装するためのものなんだから、
状態別でアッパーキャストするならまだしも(これだってクラスの内容によっては
何が起きるか分からなくなるので、実装依存もいいとこなんだが)、正直その使い方は
およそ賛成しかねるなあ…。
あと、直接関係ないネタだけど。
>methodを仮想関数にすると、インライン展開できないので、
これは多くの人が誤解していることだけど、実際に仮想関数がvtable経由で
コールされるのは、アッパーキャストが絡むときのみ。
わざわざ vtable を辿らなくてもコール先が自明な場合、コンパイラは直接
関数を呼び出すコードを生成する。
inline virtual なんて、珍しくないよ?
煽るつもりじゃないのでsage
0501500
02/01/17 02:09ID:???500ゲットに免じてご勘弁。
0502名前は開発中のものです。
02/01/18 10:04ID:???>実際に仮想関数がvtable経由でコールされるのは、アッパーキャストが絡むときのみ。
まともに OOP してるなら、ベースクラス通して使う事がほとんどだと思うのですが…。
0503502
02/01/18 10:10ID:???私も vtable 書き換えなんて、よっぽどの事でもないかぎり反対です。
というかゲーム業界のプログラマって、過酷なターゲットいじり過ぎて
「まず速度ありき」なのはちょっとマズイ状況だと思う。
最適化は最後の作業ってのはソフトウェア業界の常識だと思いますけど、
そこらへんは皆さんどうお考えですか?
0504
02/01/18 10:45ID:9PXzALQL速度の前にコード無く、コードの後に速度無し。
0505名前は開発中のものです。
02/01/18 13:19ID:???0506名前は開発中のものです。
02/01/18 15:54ID:???まず、モジュール化ありき。
ボトルネックになる部分はほんの一部に過ぎない。システムを詳細な、依存関係が少ない部分にばらして
おけば、ボトルネックを見つけて改良するもの楽。(後からアルゴリズム差し替えようなんて話は、それこそ
クラスをきっちり分けてモジュール化してないと、危なくて出来ない)
0507名前は開発中のものです。
02/01/18 16:35ID:???確かに、コードを一行も書かなければ最速だわな。(違う?)
0508名前は開発中のものです。
02/01/18 17:28ID:???まともなゲームプログラマは、
C++のコードみた瞬間にアセンブリコードが浮かぶので
無駄だらけに感じるのだろう。そっとしておいてやれ。
0509名前は開発中のものです。
02/01/18 18:54ID:???0510名前は開発中のものです。
02/01/18 18:58ID:B+awXMzdしかし、vtable書き換え……俺もやめようよそれは派だな。
Cみたく完全に枯れた言語ならともかく。
0511名前は開発中のものです。
02/01/18 20:17ID:???その無駄ってのも顕微鏡で覗いてやっと分かる、みたいな
もんだしな。これからの時代はそういう人達をいかにシカトして
作業するかが問題になってくる。ん、時間が経てばいなくなるか(w
0512名前は開発中のものです。
02/01/18 20:36ID:???ウイルスも何十万集まれば風邪になるってね。
0513名前は開発中のものです。
02/01/18 20:42ID:???0514
02/01/19 02:08ID:fEUidKgQ0515名前は開発中のものです。
02/01/19 02:18ID:???どこでそういう結論になっているのか教えてちょ
SmallTalk以外は認めない、とかかな?
0516
02/01/19 02:31ID:fEUidKgQ0517名前は開発中のものです。
02/01/19 02:34ID:???おいおい(w 少なくとも C++ 相談室スレでは C++ 使って OO な設計する話で盛り上がってたぞ。
C++相談室 Part4
http://pc.2ch.net/test/read.cgi/tech/1009071535/
0518名前は開発中のものです。
02/01/19 03:06ID:???http://www.amazon.co.jp/exec/obidos/ASIN/4894714353/ref%3Dsr%5Faps%5Fd%5F1%5F1/249-8109842-4582733
こんな本も話題だったような
0519名前は開発中のものです。
02/01/19 04:13ID:???禿同。
>>515
514じゃないけど、Ruby関係のスレとかでは名文句「C++なぞ問題外」
って言われるね。漏れも(万が一)環境が許すならば C++ よりも Java や C# で逝きたい派だけど。
0520
02/01/19 04:21ID:fEUidKgQファイル分けに有り。
0521名前は開発中のものです。
02/01/19 06:25ID:???Rubyの煽りは敵を増やしただけだな。
RubyもOOPとしての完成度は低い。たかが一言語としての立場を
わきまえるべきなのだが。作者がそんな厨だからスレが荒れるんだよ。
0522名前は開発中のものです。
02/01/19 07:51ID:???言語ヲタな時点で激しく逝ってると思われ
0523名前は開発中のものです。
02/01/19 11:05ID:???Stroustrup先生自身がOO言語じゃないって言ってなかったっけか?
俺的にはOOも可能なてんこもり言語。
0524名前は開発中のものです。
02/01/19 13:15ID:???>RubyもOOPとしての完成度は低い。
どのへんが?
0525名前は開発中のものです。
02/01/19 13:41ID:???しかし、以下の欠点からRubyが使われることは将来にわたっても無いだろうと考えられる。
1:UNIX系生まれなので、@や$みたいな記号に重要な意味を持たせている(Win育ちには読みにくい)
2:実績がない。Python使ったスクリプトや大規模プログラムはいくつか例が見られるが、RubyではせいぜいがCGIで、後は誰も使わないライブラリや技術的テスト物ばかりが大量生産されている。
3:コミュニティがC++を蛇蝎のごとく嫌っている。PythonはC++とのブリッジとなるライブラリがいくつか存在している。
OO的にはどうなんかな? 上記2のように大規模プログラムが全然存在していないので、あまりありがたみを感じられる事例が存在していないだけのようにも思う。
0526危険レベル3
02/01/19 13:41ID:???0527名前は開発中のものです。
02/01/19 15:38ID:???PS2 とかは GCC って聞いたけど、それ以外は?
そっち系の方教えて下さい。
0528
02/01/19 17:34ID:sHB48RINゲームでは見た事ないなあ。
PCならMS−Cか。
0529名前は開発中のものです。
02/01/19 17:48ID:???0530名前は開発中のものです。
02/01/19 23:19ID:???C++ は
- 手続き型プログラミング
- データ抽象
- オブジェクト指向プログラミング
- 汎用プログラミング
など、複数のパラダイムを支援する言語。OOPL としてみればメタクラスが無いとかクラスが FCO では
ないなど「中途半端」な面もあるが、現実の要求に則してうまく仕様を取捨選択してある。使いこなせば
強力な言語。
っつーことで。
0531名前は開発中のものです。
02/01/19 23:23ID:???VC じゃなくて MS-C なのか?
いや、俺は XBOX は触ってないから知らないんだが。
0532
02/01/19 23:57ID:aWuoIM0Y0534名前は開発中のものです。
02/01/20 00:18ID:???ああ、それは勘違い。
ゲーム関係でコンソール/コンソールボックスといったら、いわゆるゲーム専用機のこと。汎用
の PC や Mac なんかとと対比しての呼称ね。
0535名前は開発中のものです。
02/01/20 01:03ID:ECljemOC0537名前は開発中のものです。
02/01/20 01:16ID:???ヲタ用語か? 海の向こうだと割と使われてる気がするが。
っつか、話が OO と関係ないな。終わらそう。
0538名前は開発中のものです。
02/01/20 12:39ID:???判断できないと、勇気をもって OO できないね。
で、結局パフォーマンスを気にしすぎてセコセコした設計をすると
OO のよさが活かされずに「 ゲームは特殊なんだよ。」みたいな
結論に達する厨がいる。と。
0539
02/01/20 14:30ID:5pJrXY6QだからC++以外で組んでから言えつうの!
死ね!
0540
02/01/20 14:31ID:5pJrXY6Q死ね!
0541名前は開発中のものです。
02/01/20 14:43ID:???> で、結局パフォーマンスを気にしすぎてセコセコした設計
設計段階からパフォーマンスを意識する必要は、最近はない気がするなぁ。とりあえずプロファイラ
かけてからモノをいえ、に一票。
0542名前は開発中のものです。
02/01/20 14:53ID:???少なくともPS2の場合だったら、
クラスのサイズが大きくなりすぎない事に注意すればいいだけ
だよ。
0543
02/01/20 16:10ID:5pJrXY6Qだと言う事だね。
死ね
■ このスレッドは過去ログ倉庫に格納されています