トップページgamedev
1001コメント397KB

DXライブラリ 総合スレッド 2008

レス数が950を超えています。1000を超えると書き込みができなくなります。
0001名前は開発中のものです。2008/10/25(土) 17:37:53ID:BCFbbKco
Cを習得した程度のスキルでも、
GUIのゲームを比較的容易に作成する事を可能にする、
「DXライブラリ」に関するスレッドです。

DXライブラリの詳細ついては
http://homepage2.nifty.com/natupaji/DxLib/
を参照して頂きたい。

DXライブラリに関するテクニックなどの情報交換などを行う事で、
多くのDXライブラリユーザのスキルの向上に役立てたら幸いです。

過去スレ:DXライブラリ 総合スレッド
      http://pc11.2ch.net/test/read.cgi/gamedev/1197468399/
0894名前は開発中のものです。2009/03/25(水) 09:38:24ID:YpvCJGXN
でけた thx
0895名前は開発中のものです。2009/03/25(水) 09:51:13ID:6OdRd8FO
>>891
ちょっと調べたが、簡単には無理っぽいな

試したことが無いが、
SetUseGDIFlag(TRUE)すればコモンダイアログ等のGDIの画面上乗せ出来るようだ。
メインウィンドウのHWND取得して、CreateWindowEx等のAPIで自作したウィンドウハンドルを子ウィンドウとして登録。
メッセージプロシージャ等はAddMessageTakeOverWindowすればコールバックで戻ってくる模様。
.NETではないが、コモンコントロールを扱うのなら、こういう方法しかないとおもう。

ちなみに俺はスクロールバー・ボタン等については必要になった時に自作している。
0896名前は開発中のものです。2009/03/25(水) 12:24:54ID:pfpspq1b
初心者向け3Dライブラリの条件は
C++でなく、C言語に対応していること
そして、コマンド数が多い事
単純であることだろう、よって複雑な事は出来なくても良い。

DarkGDKのコマンドリストをUPする。
コマンド名を見れば動作の予測ができるでしょう
http://www.csync.net/service/file/view.cgi?id=1237950965

0897名前は開発中のものです。2009/03/25(水) 19:28:42ID:kayJkkXd
>>893 >>895
レスTHX。ListViewとかボタン(WINAPIと同じ挙動のやつ)を
作るとなるとかなり大変だからManaged DirectXの方でやることにするわ。

0898名前は開発中のものです。2009/03/25(水) 21:17:20ID:uIkqnwHF
>>896
そもそも初心者が3Dに手を出すこと自体にかなり無理があると思うんだが。
0899名前は開発中のものです。2009/03/25(水) 22:14:20ID:T2UmaOBx
Easy3Dは初心者に対しては本当に良く出来てる
HSPで3Dってのが個人的にはありえなかった
0900名前は開発中のものです。2009/03/26(木) 00:21:46ID:XQqCSMDQ
そもそも初心者はゲームの作り方自体がわかんないと思うけどなあ
0901名前は開発中のものです。2009/03/26(木) 00:33:28ID:GwVmRN1C
DXライブラリのおかげでなんとかゲームらしきものが作れてるレベルの俺としては
3Dものなんて夢のまた夢。
0902名前は開発中のものです。2009/03/26(木) 02:33:02ID:ucYatCYF
3Dもそこまでハードルが高いとは思わないんだけどさ、
2Dと違って素材集めやモデリングが難しいんだよね。そして興味ない。
さらに3Dで作るゲームにアイデアがない。
最後に、3Dゲーって2Dゲーと違ってしょぼさが如実にあらわれるんだよね。
0903名前は開発中のものです。2009/03/26(木) 02:55:38ID:1EzpJ+ry
ハードルなんてあるのか?軸が1個増えた程度にしか・・・。
0904名前は開発中のものです。2009/03/26(木) 03:28:44ID:mGxo+8so
あたり判定やらモーションが難しいし面倒
衝突した場合、3Dの場合は食い込んで表示されて不自然だし
回転とかしたときのモデルの先端の座標やらがイメージしにくい
0905名前は開発中のものです。2009/03/26(木) 04:42:32ID:ZAixtAoM
>>903は次世代コンシューマでメインPGで何作も作ってる程の凄腕のプログラマーに違いない。
0906名前は開発中のものです。2009/03/26(木) 06:38:45ID:jGahXsLt
カメラを意識しないようなゲームなら、ホントに軸が1個増えただけだと思うよ
計算が複雑になったり、グラフィックに掛ける手間が増えるから
初心者は2Dでゲーム製作に慣れてからの方がいいとは思うけど
0907名前は開発中のものです。2009/03/26(木) 06:44:13ID:Ts2wEbx3
PRG作るときのキャラ表示って2次元のグラフィックを三次元空間に配置したほうが楽?
二次元のキャラが2マスのサイズあるので、
NPCの前に立つのと、後ろに立つので被さり表示順序を変えなきゃならん。

3Dならこんなのないだろうになぁ
0908名前は開発中のものです。2009/03/26(木) 07:38:35ID:jGahXsLt
>>907
3Dでも基本的に同じだよ
奥行きの値で表示順をソートする必要がある
0909名前は開発中のものです。2009/03/26(木) 08:50:05ID:k7PFsR0n
>>907
俺は描画オブジェクトにZ値を持たせ、描画順をstd::listで記憶して表示順序変えてるよ。
Z値が同じ値なら、Y値の設置底面(top+heihtした値)で比較し、ソートする。

たぶんこれが一番楽で一番確実。
毎フレームソートするのはバカらしいから、極力必要最低限の回数にするようにしてね。
0910名前は開発中のものです。2009/03/26(木) 09:47:36ID:Ts2wEbx3
>>909
thx.
std::listってc++か・・
0911名前は開発中のものです。2009/03/26(木) 09:59:19ID:k7PFsR0n
そうそう。これを機にSTL覚えなよ。
STLも万能ではないが、知っておくに越したこと無いね。
ちなみに、こういう並び替えが頻繁に行われるものはvectorやmapでもなく、list使うのが良い
0912名前は開発中のものです。2009/03/27(金) 07:03:04ID:2mW8DqO1
オブジェクト指向のc++のが、
何人いるかわからないNPCにとっては有効?
0913名前は開発中のものです。2009/03/27(金) 08:48:18ID:a/ry8/LD
有効。C++じゃなくても書けるが、Cで書くよりははるかに柔軟に書ける。
スプライトを扱う基底クラスを継承してNPCクラス作ればいい。

厳密に言うと何人居るかわからないのはSTLのvectorが基本。(俺ならlist使うけどな)
NPC挙動はデザインパターンでいうところのStateかとStrategy
0914名前は開発中のものです。2009/03/27(金) 22:11:00ID:cVa1f6L8
3D版で、衝突したポリゴンから法線ベクトルの取得ってできる?
0915名前は開発中のものです。2009/03/27(金) 23:21:19ID:8cy1rsqr
3Dのスレ立てて、そこで議論しれ
0916名前は開発中のものです。2009/03/28(土) 00:15:58ID:av4pjJwK
俺は907じゃないけど。

今まで作ってきた2Dゲーでは画面表示の優先度が4段階くらいしかなくて
キャラの最大数も固定にして配列を利用して順番に表示していた。

次からはもうちっと一般的な組み方をするようにしようと、
listの使い方をいくつかのサイト巡って見てみたんだけど、どう使うんですか? これ。

要素を追加とか参照する方法はいいとして……。

例えばDXライブラリ使って表示するとしたら、最低限でも
「表示優先度」「グラフィックハンドル」「表示座標(X,Y)」
が必要なわけですが、このうち「表示優先度」をlistに追加していき、最終的にソート?

でも「表示優先度」だけソートされてもしょうがない。「グラフィックハンドル」とかと繋がってないと。
とするとlistの項目に「グラフィックハンドル」その他も組み込める?

それとも、表示優先度の段階ごとにlistを用意して、それぞれに追加していく?
でもこれだと3Dゲーみたいに優先度がどこまで段階わけされるかわからない場合に使えないし……。
0917名前は開発中のものです。2009/03/28(土) 00:32:49ID:cy5L8nnk
その3つをまとめた構造体をつくって優先度をキーにソートすればいいんじゃないの?
0918名前は開発中のものです。2009/03/28(土) 02:01:13ID:z1vkTGRC
listをどう使うかなんてこのスレに関係ないだろ。
0919名前は開発中のものです。2009/03/28(土) 02:05:01ID:z1vkTGRC
……と自治っぽいことを書いておくと、何故か反発して親切な馬鹿が教えてくれるよ。
0920名前は開発中のものです。2009/03/28(土) 09:35:01ID:8c8Vy+u+
>>916
クラスないしは構造体で「表示優先度」「グラフィックハンドル」「表示座標(X,Y)」などの情報をカプセル化して梱包する。
クラスには仮想関数でdraw()を持たせる。
この"クラスのポインタ"をstd::listとしてとあるImageListクラス(Singletonオブジェクト)が一律に保持し、優先度が変更されたタイミングでsortをして常に正しい描画順位になっているようにする。
そして、描画タイミング時(毎フレームに1回)に、drawを優先順位順になめるように実行すれば良い。
これで、簡易な描画システムの完成。システムと呼べるほどの出来ではないけどな。

俺の場合、さらにScreenクラス(独自の座標系とクリッピング領域を持つ)とノード型の親子関係で持たせることで柔軟に対応している。
0921名前は開発中のものです。2009/03/28(土) 09:41:07ID:ypn63o+I
>>919 - >>920
ワロタ
0922名前は開発中のものです。2009/03/28(土) 12:58:40ID:V/znOr52
高度な話してるところ悪いんだけど初歩的な質問をさせてくれ。
ここで聞けって言われたもんで。

メニュー画面とゲーム画面を往復する度にメモリ使用量が上がってくんだけど、
読み込んだものはゲーム画面終了直前にInitSoundMemとInitGraphで全て削除するようにしても
上昇量よりはるかに小さい分しか変わらないし、
じゃあ今度は画像の読み込みを全部削除してみたら(画面は真っ暗になるけど)きれいさっぱり解決したから
やっぱ画像関係に原因があるのはわかったんだけど、

本題
DXライブラリって画像関係で、読み込んだの以外に変なのを生成したりしてるんですか?

あとどうやらそのゲーム画面で初めて登場する画像が描写される度にもメモリ使用量がちょっと上がるみたい。
これも画面真っ暗にしたらきれいさっぱりいった。
0923名前は開発中のものです。2009/03/28(土) 13:40:42ID:miSl0Len
>>879
代入なら精度は落ちないけど、計算すると精度は落ちるよ。
double同士の四則演算をすると DxLib_Init前と後で、精度が違うから
同じ計算をしても結果が異なることがある。
0924名前は開発中のものです。2009/03/28(土) 13:50:45ID:8c8Vy+u+
>>923
何度読んでも俺には何言ってるのか分からん。
精度が違うって何言ってる・・・。
0925名前は開発中のものです。2009/03/28(土) 14:00:54ID:miSl0Len
>>924
わかりにくくてすまん。
例を書いてみた。

double a = 0;

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
double v1 = 3.1415926535897931 + a;
ChangeWindowMode(TRUE);
if(DxLib_Init() < 0) return false;
double v2 = 3.1415926535897931 + a;
return 0;
}
v1と v2の値を比べてみてくれ。
0926名前は開発中のものです。2009/03/28(土) 14:04:24ID:miSl0Len
>>925
あ、return falseはまずかった。
return 0の間違いってことで。
0927名前は開発中のものです。2009/03/28(土) 14:08:18ID:8c8Vy+u+
あ。わざわざ例挙げてもらってすまん。良いたい事は分かった。
DXライブラリでDirect3D使う場合だとFpuPreserveしてるからdouble型の演算レジスタ弄ってるわけね。
俺3D機能使わずにDirectDrawの方で書いてるから気づかなかったわ。
0928名前は開発中のものです。2009/03/28(土) 14:48:40ID:8c8Vy+u+
>>925,926
Direct3DのFPU関連の対処法についてDXライブラリのソース調べてみたら、
// FPUの精度を落とさない設定を使用するかどうかを設定する、DxLib_Init を呼び出す前のみ有効( TRUE:使用する(精度が落ちない) FALSE:使用しない(精度を落とす(デフォルト) )SetUseFPUPreserveFlag( int Flag );
を見つけたよ。
double型を使う場合はTRUEにしても良いかもね。(精度は上がるが速度が落ちるので好みに)

でも、俺はfloat派だから関係ないが〜。
0929名前は開発中のものです。2009/03/28(土) 15:03:24ID:alJS1U5l
パンツってみんな脱いでるの?あとカップルいるけど警察に捕まったりしないの?
0930名前は開発中のものです。2009/03/28(土) 16:05:39ID:8c8Vy+u+
>>922
メモリ使用量の上昇具合ってどんな感じ?
コードを晒してくれると原因が分かりやすいんだがな。

画面遷移時に使われなくなったハンドルについて
・イメージハンドルはDeleteGraphで個別に全て解放をしているか?
・フォントの再生成をしていないか?
を見直してみてくれ。
特にフォントは文字サーフェスをキャッシュしているから、DeleteFontToHandleしないとメモリが解放されない。
その上で、フォントの再生成をしてしまうとメモリ使用量がじょじょに増大する結果になるよ。
0931名前は開発中のものです。2009/03/28(土) 16:48:52ID:ShTXh3pj
>>930

・メモリの上昇具合
メ=メニュー画面、ゲ=ゲーム画面
メ59M
ゲ108M
メ107M
ゲ112M
メ118M
ゲ124M
メ129M

・イメージハンドルはDeleteGraphで個別に全て解放をしているか?
さっき言ったとおり、Init〜で全部まとめて消去してる。

・フォントの再生成をしていないか?
よこわからないがフォント関係はいじらずデフォルト?の文字で単純に出力してるが、それでもアレ?
ていうかさっき言ったとおり画像を読み込むところだけ切り取ったら全部解決したので画像関係のアレだと思うんだが……
0932名前は開発中のものです。2009/03/28(土) 17:33:23ID:feWgJMZK
切り取らずに、画像を読み込み終えたところでInit〜してみたらどうなるかな。
0933名前は開発中のものです。2009/03/28(土) 17:40:00ID:8c8Vy+u+
>>931
>ていうかさっき言ったとおり画像を読み込むところだけ切り取ったら全部解決したので画像関係のアレだと思うんだが……
ちょっとこの文章の意味がわからんな。
画像を読み込むのを切り取っちゃったら画像が読み取れないんじゃないか?
それとも、状態変移での2度目に読み込みを飛ばすってこと?
でもその前にInitGraphしてるのなら、グラフィックハンドルは解放されて無効になってるはずだよ。(描画できないはず)

えっととりあえず言うと、画面遷移時にInitGraphで全部消しちゃうのはオススメできない。
使い終わったグラフィックハンドルについては面倒でも個別にDeleteGraphしてみるのが良い。(サウンドもDeleteSoundMemを使う)
俺の場合これで画面遷移時でもメモリ上昇は変わらないよ。

未だ問題あるようなら、同じグラフィックハンドルに画像を読み直す命令としてReloadGraphというのがあるので、これで上書き読み込みする手もある。
あと、DXライブラリでのメモリ使用量と数を確認する命令DxGetAllocSizeとDxGetAllocNumを使って、どのタイミングで発生するのかを確認するのも手。

フォントについてはCreateFontHandleしてないなら問題ないよ。
0934名前は開発中のものです。2009/03/28(土) 18:38:40ID:feWgJMZK
>じゃあ今度は画像の読み込みを全部削除してみたら(画面は真っ暗になるけど)きれいさっぱり解決したから
>やっぱ画像関係に原因があるのはわかったんだけど、

って事でしょう。


>えっととりあえず言うと、画面遷移時にInitGraphで全部消しちゃうのはオススメできない。

これ、気になるので、よければその理由を教えて欲しい。
0935名前は開発中のものです。2009/03/28(土) 19:05:08ID:ShTXh3pj
>>932 読み込んだ直後にInit〜やったけどダメだった。なので

>>933 Deleteでそれぞれやってみたけどやっぱダメだった……
あと、WaitTimerとかでところどころ止めながその隙にタスクマネージャで見る方法でもいいよね?
上昇のタイミングはもちろん画像読み込みの時で、問題なのはデリートの時に少ししか下がらないで、
あと各画像がそのゲーム画面で初めて表示されるときも微量ずつ謎の上昇……

ていうか普通はデリートすればあっさり上がるんだな……なんでデリートがちょっとしか効かないんだ。
0936名前は開発中のものです。2009/03/28(土) 19:43:04ID:8c8Vy+u+
>>944
リソースの管理はなるべくプログラマが厳密にした方が良いって理由。
InitGraphだとMakeScreenやMakeGraphやCreateGraphFromSoftImageで作った画像も全部丸ごと削除されてしまうから。
DeleteGraphなら無効なハンドル渡したときに戻り値で-1返すし、どのハンドルが解放されたのかを明示的に指示した方が分かりやすい。
自分はグラフィックハンドル周りはクラスでカプセル化してデストラクタで必ずDeleteGraphして解放するようにしてる。

>>935
>あと各画像がそのゲーム画面で初めて表示されるときも微量ずつ謎の上昇……
これは正常な動作だよ。最初の表示1回目はメモリ確保される。

うーん。どっかでDXライブラリ以外の箇所でnew(malloc)したメモリをdelete(free)せずにメモリリークしてないかい?
MSVC環境なら_CrtSetDbgFlag()があるからチェックしてみて。
0937名前は開発中のものです。2009/03/28(土) 20:01:35ID:ShTXh3pj
>>936 そうか最初の1回は上がって普通なのか。
あとメモリの動的確保ならやってない。画像関係の問題ってわかっててるし。
CrtSetDbgFlagって言うのをググってみたけどデバッグ環境が必要みたいだね。
そりゃ無理な話だ……

あまりしたくないんだけど、ゲーム画面のコードを晒せば原因判明するかな?
0938名前は開発中のものです。2009/03/28(土) 20:15:33ID:8c8Vy+u+
Borland C++使ってるのなら_CRT関数は使えない。Microsoft Visual Studio専用関数だからね。
さすがに現状で、要因を探すのは難しいな。
0939名前は開発中のものです。2009/03/28(土) 21:42:26ID:ShTXh3pj
それは……晒しても無駄って意味だよな。
0940名前は開発中のものです。2009/03/28(土) 21:46:24ID:8c8Vy+u+
いや、発言だけじゃ原因が特定できないってこと。
コード出してくれればもちろん見るよ。
0941名前は開発中のものです。2009/03/28(土) 22:09:09ID:ShTXh3pj
http://www1.axfc.net/uploader/He/so/210050
pass : dx
根っからの初心者ゆえ、稚拙かつわかりにくいけどお願いします。
0942名前は開発中のものです。2009/03/28(土) 22:18:26ID:8c8Vy+u+
>>941
DLしてみたよ。想像以上のソースだったw

えっと、原因はLoadSoftImageに対して、DeleteGraphを使ってるところ。
DeleteSoftImageを使いましょう。
0943名前は開発中のものです。2009/03/28(土) 22:39:34ID:ShTXh3pj
ちょ、ちょっと待っててね……そのまんま範囲内全置換しても強制終了する。原因究明中。
0944名前は開発中のものです。2009/03/28(土) 22:50:21ID:JfTJy2mS
凄まじいソースだなww
0945名前は開発中のものです。2009/03/28(土) 22:58:12ID:X3zs6AFo
前にもこんなソースを見たことがあるぞ
0946名前は開発中のものです。2009/03/28(土) 23:17:44ID:ShTXh3pj
ID:8c8Vy+u+ありがとう! 100kぐらいずつしか上がらなくなった! 感謝感激雨霰、3か月悩み抜いた甲斐があったってもんですぜ。

>>945 晒したのは初めてだぜ。

あと、ソース長くてもミスが見つかりにくくなるぐらいなもんだよな、問題は……
0947名前は開発中のものです。2009/03/28(土) 23:23:41ID:nBMPzKvQ
>>あと、ソース長くてもミスが見つかりにくくなるぐらいなもんだよな、問題は……
それが一番困ると思うぜ
0948名前は開発中のものです。2009/03/28(土) 23:27:14ID:JfTJy2mS
分割オヌヌメ
れっつextern
0949名前は開発中のものです。2009/03/28(土) 23:29:47ID:ShTXh3pj
ああそうか。externが原因の1つかもしれないと思ってできるだけ避けてたんだ。
だけど大丈夫なのか。じゃあ関数使いまくれるぜ。
0950名前は開発中のものです。2009/03/28(土) 23:30:56ID:8c8Vy+u+
>>946
ういうい。どうもです。
コード晒すのは勇気いるけど、コードを隠すプログラマは例外なくダメプログラマに育つからね。
その点、コードを出したのはすばらしいと思うよ。3ヶ月悩んだものがコード出したら10分足らずで解決できたように早期解決できるし両得だ。

あと、デバッグ環境が無いみたいだけどVisual C++ 2008 Express Edition(無償)を使うと良いよ。
http://www.microsoft.com/japan/msdn/vstudio/Express/
デバッグが使えるのは大きいし、コンパイラの性能が良いから、Borland C++5.5よりも大体1.2倍ぐらいはプログラムが速くなるさ。
0951名前は開発中のものです。2009/03/28(土) 23:46:31ID:ShTXh3pj
なんかSP1てついてるけどこれでいいんだな……やてみるぜ。ありがとう。
0952名前は開発中のものです。2009/03/29(日) 00:08:50ID:wJL07IJT
>>951
そうそう。それでok
VS2008へのDXライブラリの組み込み方はDXライブラリ公式サイトに書いてあるよ。
http://homepage2.nifty.com/natupaji/DxLib/dxuse_vc2008express.html
0953名前は開発中のものです。2009/03/29(日) 00:20:45ID:IeRll+oU
>>945
おそらくそれはしょぼんのアクションだ。
0954名前は開発中のものです。2009/03/29(日) 00:33:04ID:6OZkFx/C
>>953
ああ、それだわ
>>136-145 あたりでも話題になってるな
0955名前は開発中のものです。2009/03/29(日) 00:39:32ID:wJL07IJT
>>953
すごいなこれ。
リファクタリングの腕がつくから試してみようかと思ったが、
さすがにマジックナンバーが多すぎてちょっと無理っぽいわ。

//自由な値
int xx[91];
double xd[11];
string xs[31];
とか無茶すぎるだろw
0956名前は開発中のものです。2009/03/29(日) 00:56:39ID:8NyFLpVN
BCCdeveloperでは大丈夫だったのに
全部の関数で「〜で既に宣言されています」
って出る……何のためのヘッダだよ……
0957名前は開発中のものです。2009/03/29(日) 00:57:59ID:8NyFLpVN
あ、ID変わってる。どうも、ショボン二世です。
0958名前は開発中のものです。2009/03/29(日) 01:00:10ID:wJL07IJT
>>956
ヘッダの先頭に
#pragma once
と書く
0959名前は開発中のものです。2009/03/29(日) 01:04:35ID:wJL07IJT
#pragma onceだとVCでしか使えないから、
正確にはインクルードガードをするのが良いんだけどね。(__HOGE_H__は自分のヘッダファイル名)

#ifndef __HOGE_H__
#define __HOGE_H__
(ヘッダ本文)
#endif // __HOGE_H__

ま、どうせVCしか使わないんだろうからどっちでも良いよ。
0960名前は開発中のものです。2009/03/29(日) 01:19:07ID:4SqorqSC
3ヶ月解けなかったものを10分で解けちゃう人がいると聞いて飛んできたわけじゃないんですけど、
C++でメンバ関数ポインタって使ってもいいもんなんですかね。
goto思想のようなものでもお行儀のようなものでもいいんだけど、普通はどんなもんか教えてください。
ついさっきメンバ関数ポインタっぽいものがあったらスマートに書けるなーと思って検索したら発見しました。
もし具体例が必要なら提示しますので教えてください。
0961名前は開発中のものです。2009/03/29(日) 01:22:41ID:8NyFLpVN
全く意味がわからない。・゚゚(ノД`)
今まで何を勘違いしたか知らないけどヘッダファイルに直接関数を書いてた。
BCCに帰りたくなったけど少しでも軽くするためにがんばります。
修行の旅に出ますありがとうございましたノシ
0962名前は開発中のものです。2009/03/29(日) 01:39:41ID:wJL07IJT
>>960
staticなメンバ関数について関数ポインタをとるのなら文法的には合ってるが作法的にはよろしくないとは思う。
(クラスは設計者と利用者が異なる観点ではオーバーライドされる可能性があるという意味で。)

けれど仕様上、静的なコールバックを要求する場合(Windowsメッセージプロシージャ等)だと、
staticなメンバ関数を指定した方が読みやすいと俺は思う。
この場合、staticメンバ変数から、Singletonオブジェクトを参照してインスタンスを得る方法を自分は多用しています。

自分で設計するのであれば、C++なら関数ポインタを使わずに、インターフェースクラスから派生する手法だったり、
純仮想関数をオーバーライドする設計(いわゆるStrategyパターン)を使うかな。

ただ、タスクのようなごった煮の振る舞いをしたいのであれば関数ポインタを使うこともしばしばあります。
0963名前は開発中のものです。2009/03/29(日) 01:41:04ID:wJL07IJT
×この場合、staticメンバ変数から、Singletonオブジェクトを参照してインスタンスを得る方法を自分は多用しています。
○この場合、staticメンバ関数内で、Singletonオブジェクトを参照してインスタンスを得る方法を自分は多用しています。
0964名前は開発中のものです。2009/03/29(日) 02:00:32ID:4SqorqSC
>>962
staticではないメンバ関数ポインタでした。
個人製作だから、という言い訳の前提のもと、シングルトンデザパタとかも使わずアプリケーションの最初で1つ生成し、アプリケーションの最後で破棄されるっていうクラスの中なんですが、
staticなクラスにするのもいいのですが今回の話とは関係なさそうなので割愛します。

問題の箇所は、MyClassオブジェクトを生成したint main()から見て、あるMyClass.A()は特定の1度しか呼ばれず、あるMyClass.B()は1フレーム中で毎回呼ばれます。
そして、MyClass.B()はMyClass.C()やMyClass.D()やMyClass.E()のうちどれかを呼びます。
当然B()に呼ばれるC()やD()やE()も毎回呼ばれないと困るのですが、呼ぶ先のメソッドが変わっても困るのです。
そこで、例えばランダムにC()D()E()のどれか一つを呼ぶことを決定したいのですが、
フラグ等を使ってB()内で一度だけ決定するのもいいのですが、
A()で決定しメンバ関数ポインタに入れておき、後にB()で決定された先を読んでもらおうという感じです。
A()では同じような処理を複数するので一括しておきたいのと、C()D()E()のようなメソッドはさらに多くあるので
A()内でメンバ関数ポインタで管理した方がいいかなと思いました。
乱文ごめんなさい。
0965名前は開発中のものです。2009/03/29(日) 02:22:47ID:wJL07IJT
>>964
言っていることをそのまま実装すると
staticでないメンバ変数の関数ポインタ(MyClass.B()〜C())を参照するとエラー出るよね。
「仮想関数のポインタが参照されました」というのが。

デザパタを使いたくないのであれば、方法は1つしかない。

メンバ関数のアドレスをthisポインタからのオフセットアドレス値から算出するという手段で、けっこう裏技。
かなりの裏技でC++に熟知してないと普通は使わない方法だね。
実装方法は
http://www7b.biglobe.ne.jp/~robe/cpphtml/html03/cpp03057.html
このサイトの57章と58章に書いてあるよ。
0966名前は開発中のものです。2009/03/29(日) 03:00:28ID:4SqorqSC
>>965
まさにそのサイトも見て実装しました。
そしてまさにその使い方の事を聞きたかったのです。分かりにくい説明でごめんなさい。

ただ参考になりました。ありがとうございました。
デザインパターンも勉強してみて試行錯誤してみたいと思います。

蛇足ですが、C++でゲーム作ると(staticな?)アプリケーションクラスを一つ作って、
int main()の中のメインループの中でアプリケーションクラスを呼び出すことから始まりますよね。
で、オブジェクト指向っぽく設計とか考えてやっても結局アプリケーションクラスの中でCの構造化プログラミングをしてるだけっぽくなっちゃってました。
今回もメンバ関数ポインタを呼ぶのも関数ポインタを使った構造化プログラミングっぽいです。。
他の人のソースを眺めてみると頻繁にインスタンスを生成したり破棄したりしてますが、
自分の書いたものはあまりせず、結局全部グローバル関数でも同じじゃん!みたいななっちゃいます。
一応継承とかも使ってみるも、ちょっとしたコードの再利用程度でしかなく、ポリモーフィズムなんて実現できないです。
まあ経験が足りないんでしょうね。。精進します。
0967名前は開発中のものです。2009/03/29(日) 03:09:57ID:wJL07IJT
>>964のやりたい処理はこれでOKなハズ
サンプルソース書いたよ
http://www.dotup.org/uploda/www.dotup.org13651.cpp.html
0968名前は開発中のものです。2009/03/29(日) 03:21:31ID:4SqorqSC
>>967
わざわざありがとうございます。
ソース見させていただきました。
ほぼ同じように実装しました。
実際にはポインタに入る関数はA()が決めるのですが同じですね。
0969名前は開発中のものです。2009/03/29(日) 03:22:49ID:uaYHl2HP
>>960
普通につかって全く問題ない。Cとは表記が違うのだけ注意。
他のクラスには適用できないし、キャストも許可されないので、むしろCより安全に使える

>>964だとこんなかんじ

class Hoge {
public:
Hoge() : target(NULL) {}
typedef void (Hoge::*TargetType)(int param);
TargetType target;
void A() {
TargetType funcs[] = { &Hoge::C, &Hoge::D, &Hoge::E };
target = funcs[rand() % 3];
}
void B(int param) { (this->*target)(param);}
void C(int param) { printf("C called:%d", param);}
void D(int param) { printf("D called:%d", param);}
void E(int param) { printf("E called:%d", param);}
};

>>965
「メンバ関数ポインタ」について調べることをおすすめする
0970名前は開発中のものです。2009/03/29(日) 03:25:13ID:uaYHl2HP
てか、965さんちゃんとわかってるんじゃん…

裏技でもなんでもないよってことで。
0971名前は開発中のものです。2009/03/29(日) 03:30:37ID:wJL07IJT
>>966
おっと、書き込む前にリロードすればよかった。
デザパタは相当C++やJavaが相当手馴れた頃に初めて見てみると、目から鱗な考え方なんだ。
素人が下手に手を出しても意味が分からないまま終わっちゃう。
大規模アプリを作れるレベルになって設計と実装に悩みだした頃に読むと良いよ。
ゲーム製作に特に使うのはSingleton,Strategy,TemplateMethod,Facade辺り。次にAbstractFadtoryやObserver。後のはほとんど使わない。

オブジェクト指向がする必要の無い局面って結構あるから、
何が何でもオブジェクト指向にこだわって実装していくのも逆に生産性が下がるというのは966も体感していると思う。
クラスは拡張性と多様性を残しつつ、YAGNIの原則で最低限だけを実装していく。というのが一番の理想。これが中々難しいけどね。
自分は、時にベタのCで書くこともあって、C++じゃご法度なextern宣言も使ったりする。(理由はめんどくさいという一点で)
インスタンスの生成/破棄はなるべく少ない方がパフォーマンスはモチロン出るので、966の書くプログラムは良いコードだと思うけどね。
0972名前は開発中のものです。2009/03/29(日) 03:33:52ID:uaYHl2HP
ちょっと補足。

同じようなオブジェクトの微妙な動作違い、なら、設計的には
インターフェースを継承してオーバライドしたほうがいい。

この手法は同一オブジェクト内でのステート処理にむいてる。
何度も呼ばれて判定のオーバーヘッドの影響が無視できないような場合には特に有効。
0973名前は開発中のものです。2009/03/29(日) 03:40:51ID:wJL07IJT
>>970
もちろん知ってるさ。C/C++は20年選手に逝きそうなんだ……。
裏技扱いしたのは、理由があって、
多重継承をした仮想関数(純ではない)のアドレスを取得しようとして、thisポインタのサイズ(4byte)が変わる為に上手くアドレスが取れないことが以前にあった。(オフセット値がなぜかずれるためにアラインメント調整が必要になる)
という理由でコンパイラによっては非推奨な書き方だったりするんだ。
これはコンパイラのバグで、TurboC++ではダメだった記憶がある。
MSVCではたぶん大丈夫だが、一応使わないでおこうとしてた。
0974名前は開発中のものです。2009/03/29(日) 03:45:29ID:wJL07IJT
ごめん。TurboC++だったか記憶にない。CodeWarriorだったかもしれん。
どちらにしても15年前ほど前の事だったからたぶん今では問題ないと思う。
0975名前は開発中のものです。2009/03/29(日) 03:45:43ID:4SqorqSC
>>969
ふむふむ、全く問題ないのですね!
提示してくれたソースもよくわかるのですが、た…typedef…。
勉強不足のためなんとなくでしかわからないですがなんとなく分かった感じです。
こんな感じでもいいですかね?
class Hoge {
public:
void (Hoge::*pf)(int param);
void A(int x) {
if(x == 0) pf = &Hoge::C;
if(x == 1) pf = &Hoge::D;
if(x == 2) pf = &Hoge::E;
}
void B(int param) { (this->*pf)(param);}
void C(int param) { printf("C called:%d", param);}
void D(int param) { printf("D called:%d", param);}
void E(int param) { printf("E called:%d", param);}
};


int main(){

Hoge obj;
int i;
scanf("%d", &i);
obj.A(i);

obj.B(10);
return 0;
}
0976名前は開発中のものです。2009/03/29(日) 03:53:35ID:uaYHl2HP
大先輩!失礼いたしました…

あー、コンパイラのバグ……。そういうのは一度ふむと使わなくなりがちですな(苦笑)

状態遷移系の処理の他だと、半自動のバインド処理の類を書くときとかに、
テンプレートと組み合わせてばりばり使ってたりします。
0977名前は開発中のものです。2009/03/29(日) 03:57:18ID:uaYHl2HP
>>975
typedefは、宣言した複雑な型をシンプルに表記できて、
書き方覚えるととてもすっきりするので、時間あったら勉強してみてください

表記はそれで特に問題はないですが、その条件判定なら
switch つかったほうがいいと思いますです。
0978名前は開発中のものです。2009/03/29(日) 04:13:27ID:4SqorqSC
なんという頼もしいスレ…
起きててよかった。
勉強してきます=3
0979名前は開発中のものです。2009/03/29(日) 07:10:28ID:wuoKvdm5
まーたDXライブラリと関係ない話して。
初心者相手に技術自慢したいならc++関係のスレに行けばいいのに。
そこでは相手にもされない程度なのか?



DXライブラリ
0980名前は開発中のものです。2009/03/29(日) 07:26:38ID:vMEVjIQX
それだけのベテランがDXライブラリを使ってる(のだろう)事が驚き。

俺はCについてはド素人同然なので、いろいろ教えてもらえるのは助かる。
確かにスレ違いではあるんだが、DXライブラリを使ってること前提で
話をしたい場合もあるし。
0981名前は開発中のものです。2009/03/29(日) 10:08:36ID:BGS9yVjy
>>980
趣味でゲーム作ってるのが長い人には、Cの書き方でパパーッと書き上げる事もできるし、
(Windows95の頃から始めたような人なら短いものならOOじゃない方がある程度の大きさでも楽だったりするしね。)
3Dに手出す(主にデータ的な部分)のが面倒な人には、
余計なモンついてなくて2Dに特化してるのに、 変な癖が少ないから使いやすい。
あと、最初からゲームパッドとかに対応は何気に使えるし。

車輪の再開発をやってきた様な人には、
ソースもあるからちょっとだけ手を加えたい時とかも 其れが可能で、
わざわざRequestしないで良いのは、時間的にもモチベーション的にも良い選択肢。

初心者にも優しいライブラリだけど、其れだからといって
昔のHSPみたいに、他の言語知ったら使いたくなくなるような不自由さがあるわけでもない。
まぁ、DirectXバリバリつかうぜ!!って人とかには別だろうけど。
0982名前は開発中のものです。2009/03/29(日) 12:18:31ID:eagJL9bR
>>973
それバグでもなんでもねえし、
ポインタのサイズは変わらないだろ
0983名前は開発中のものです。2009/03/29(日) 13:11:06ID:Zf+/7kJf
普段はこのスレは過疎ってるから別にいいじゃないのか? DXライブラリでゲーム作るテクとしてメンバ関数ポインタを使うこともあるかもしれないしさ。

>>982
正確に書くと、継承した場合のメンバ関数ポインタのサイズが4バイトとは限らない(コンパイラ依存)
多重継承や仮想継承をしている場合、正しいポインタサイズを返すために8バイトや12バイトとなることがある。
しかし、昔のバグコンパイラではこの点が考慮されておらず必ず4バイト固定だった時代があり、派生や仮想関数を呼び出そうとするとアラインメントを調節する必要があった。
ということ。ポインタは必ず4バイトというのは早計だよ。
0984名前は開発中のものです。2009/03/29(日) 18:18:24ID:eagJL9bR
>>983
何故得意気なのか理解できんが、
それはサイズが変わるとは言わないだろ?
結局のところ、静的なサイズは確定している。
0985名前は開発中のものです。2009/03/29(日) 21:00:34ID:aWInPsJ8
>>984
RTTIしていると大問題。

なんか、微妙にスレ違いだし、
偉そうにしているといわれたようなので黙って老害は去りますね。
失礼しやした。
0986名前は開発中のものです。2009/03/29(日) 22:56:36ID:8b86AGfH
どこが得意気なのやら

で、次スレはどうするんよ
0987名前は開発中のものです。2009/03/30(月) 00:07:56ID:Ui9Ndm7F
DXライブラリ総合スレッドその3、で建てればいいんじゃね。
0988名前は開発中のものです。2009/03/30(月) 01:19:18ID:Y8nEXzvT
>>990頼んだ
0989名前は開発中のものです。2009/03/30(月) 01:54:36ID:1JQfO1aW
>静的なサイズは確定している

> RTTIしていると大問題。

会話になってねぇww
0990名前は開発中のものです。2009/03/30(月) 18:27:06ID:II/eiBAq
質問です

{
{   //1フレーム間での処理
  A  ;
  B  ;
  C  ;
}
ScreenFlip();
}

すごく大まかに言って↑このようにゲーム作ってるのですが
CheckHitKeyの判定ってって「フレームの最初のみ」に行われるんでしょうか?
それとも「ifの処理があるごと」なんでしょうか?

もし後者ならif CheckHitKey(SPACE)==1 みたいな処理をA部とB部両方に入れた場合、
Aが行われてる瞬間にSPACE離しちゃったら
Aは行われてBは行われないっていうことも起きちゃうんでしょうか?



0991名前は開発中のものです。2009/03/30(月) 18:39:19ID:x1tfO2A2
最初の大括弧はmainでその次はforとかのループの括弧か…?
0992名前は開発中のものです。2009/03/30(月) 18:42:02ID:b98OMwXU
int GetHitKeyStateAll( char *KeyStateBuf ) ;
を使えば起きない
0993名前は開発中のものです。2009/03/30(月) 18:43:28ID:II/eiBAq
>>991
そんな感じです。すみません。
>>992
ありがとう
調べてみます
レス数が950を超えています。1000を超えると書き込みができなくなります。