DXライブラリ 総合スレッド 2008
レス数が1000を超えています。これ以上書き込みはできません。
0001名前は開発中のものです。
2008/10/25(土) 17:37:53ID:BCFbbKcoGUIのゲームを比較的容易に作成する事を可能にする、
「DXライブラリ」に関するスレッドです。
DXライブラリの詳細ついては
http://homepage2.nifty.com/natupaji/DxLib/
を参照して頂きたい。
DXライブラリに関するテクニックなどの情報交換などを行う事で、
多くのDXライブラリユーザのスキルの向上に役立てたら幸いです。
過去スレ:DXライブラリ 総合スレッド
http://pc11.2ch.net/test/read.cgi/gamedev/1197468399/
0951名前は開発中のものです。
2009/03/28(土) 23:46:31ID:ShTXh3pj0952名前は開発中のものです。
2009/03/29(日) 00:08:50ID:wJL07IJTそうそう。それでok
VS2008へのDXライブラリの組み込み方はDXライブラリ公式サイトに書いてあるよ。
http://homepage2.nifty.com/natupaji/DxLib/dxuse_vc2008express.html
0953名前は開発中のものです。
2009/03/29(日) 00:20:45ID:IeRll+oUおそらくそれはしょぼんのアクションだ。
0954名前は開発中のものです。
2009/03/29(日) 00:33:04ID:6OZkFx/Cああ、それだわ
>>136-145 あたりでも話題になってるな
0955名前は開発中のものです。
2009/03/29(日) 00:39:32ID:wJL07IJTすごいなこれ。
リファクタリングの腕がつくから試してみようかと思ったが、
さすがにマジックナンバーが多すぎてちょっと無理っぽいわ。
//自由な値
int xx[91];
double xd[11];
string xs[31];
とか無茶すぎるだろw
0956名前は開発中のものです。
2009/03/29(日) 00:56:39ID:8NyFLpVN全部の関数で「〜で既に宣言されています」
って出る……何のためのヘッダだよ……
0957名前は開発中のものです。
2009/03/29(日) 00:57:59ID:8NyFLpVN0958名前は開発中のものです。
2009/03/29(日) 01:00:10ID:wJL07IJTヘッダの先頭に
#pragma once
と書く
0959名前は開発中のものです。
2009/03/29(日) 01:04:35ID:wJL07IJT正確にはインクルードガードをするのが良いんだけどね。(__HOGE_H__は自分のヘッダファイル名)
#ifndef __HOGE_H__
#define __HOGE_H__
(ヘッダ本文)
#endif // __HOGE_H__
ま、どうせVCしか使わないんだろうからどっちでも良いよ。
0960名前は開発中のものです。
2009/03/29(日) 01:19:07ID:4SqorqSCC++でメンバ関数ポインタって使ってもいいもんなんですかね。
goto思想のようなものでもお行儀のようなものでもいいんだけど、普通はどんなもんか教えてください。
ついさっきメンバ関数ポインタっぽいものがあったらスマートに書けるなーと思って検索したら発見しました。
もし具体例が必要なら提示しますので教えてください。
0961名前は開発中のものです。
2009/03/29(日) 01:22:41ID:8NyFLpVN今まで何を勘違いしたか知らないけどヘッダファイルに直接関数を書いてた。
BCCに帰りたくなったけど少しでも軽くするためにがんばります。
修行の旅に出ますありがとうございましたノシ
0962名前は開発中のものです。
2009/03/29(日) 01:39:41ID:wJL07IJTstaticなメンバ関数について関数ポインタをとるのなら文法的には合ってるが作法的にはよろしくないとは思う。
(クラスは設計者と利用者が異なる観点ではオーバーライドされる可能性があるという意味で。)
けれど仕様上、静的なコールバックを要求する場合(Windowsメッセージプロシージャ等)だと、
staticなメンバ関数を指定した方が読みやすいと俺は思う。
この場合、staticメンバ変数から、Singletonオブジェクトを参照してインスタンスを得る方法を自分は多用しています。
自分で設計するのであれば、C++なら関数ポインタを使わずに、インターフェースクラスから派生する手法だったり、
純仮想関数をオーバーライドする設計(いわゆるStrategyパターン)を使うかな。
ただ、タスクのようなごった煮の振る舞いをしたいのであれば関数ポインタを使うこともしばしばあります。
0963名前は開発中のものです。
2009/03/29(日) 01:41:04ID:wJL07IJT○この場合、staticメンバ関数内で、Singletonオブジェクトを参照してインスタンスを得る方法を自分は多用しています。
0964名前は開発中のものです。
2009/03/29(日) 02:00:32ID:4SqorqSCstaticではないメンバ関数ポインタでした。
個人製作だから、という言い訳の前提のもと、シングルトンデザパタとかも使わずアプリケーションの最初で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言っていることをそのまま実装すると
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まさにそのサイトも見て実装しました。
そしてまさにその使い方の事を聞きたかったのです。分かりにくい説明でごめんなさい。
ただ参考になりました。ありがとうございました。
デザインパターンも勉強してみて試行錯誤してみたいと思います。
蛇足ですが、C++でゲーム作ると(staticな?)アプリケーションクラスを一つ作って、
int main()の中のメインループの中でアプリケーションクラスを呼び出すことから始まりますよね。
で、オブジェクト指向っぽく設計とか考えてやっても結局アプリケーションクラスの中でCの構造化プログラミングをしてるだけっぽくなっちゃってました。
今回もメンバ関数ポインタを呼ぶのも関数ポインタを使った構造化プログラミングっぽいです。。
他の人のソースを眺めてみると頻繁にインスタンスを生成したり破棄したりしてますが、
自分の書いたものはあまりせず、結局全部グローバル関数でも同じじゃん!みたいななっちゃいます。
一応継承とかも使ってみるも、ちょっとしたコードの再利用程度でしかなく、ポリモーフィズムなんて実現できないです。
まあ経験が足りないんでしょうね。。精進します。
0967名前は開発中のものです。
2009/03/29(日) 03:09:57ID:wJL07IJTサンプルソース書いたよ
http://www.dotup.org/uploda/www.dotup.org13651.cpp.html
0968名前は開発中のものです。
2009/03/29(日) 03:21:31ID:4SqorqSCわざわざありがとうございます。
ソース見させていただきました。
ほぼ同じように実装しました。
実際にはポインタに入る関数はA()が決めるのですが同じですね。
0969名前は開発中のものです。
2009/03/29(日) 03:22:49ID:uaYHl2HP普通につかって全く問題ない。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裏技でもなんでもないよってことで。
0971名前は開発中のものです。
2009/03/29(日) 03:30:37ID:wJL07IJTおっと、書き込む前にリロードすればよかった。
デザパタは相当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もちろん知ってるさ。C/C++は20年選手に逝きそうなんだ……。
裏技扱いしたのは、理由があって、
多重継承をした仮想関数(純ではない)のアドレスを取得しようとして、thisポインタのサイズ(4byte)が変わる為に上手くアドレスが取れないことが以前にあった。(オフセット値がなぜかずれるためにアラインメント調整が必要になる)
という理由でコンパイラによっては非推奨な書き方だったりするんだ。
これはコンパイラのバグで、TurboC++ではダメだった記憶がある。
MSVCではたぶん大丈夫だが、一応使わないでおこうとしてた。
0974名前は開発中のものです。
2009/03/29(日) 03:45:29ID:wJL07IJTどちらにしても15年前ほど前の事だったからたぶん今では問題ないと思う。
0975名前は開発中のものです。
2009/03/29(日) 03:45:43ID:4SqorqSCふむふむ、全く問題ないのですね!
提示してくれたソースもよくわかるのですが、た…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:uaYHl2HPtypedefは、宣言した複雑な型をシンプルに表記できて、
書き方覚えるととてもすっきりするので、時間あったら勉強してみてください
表記はそれで特に問題はないですが、その条件判定なら
switch つかったほうがいいと思いますです。
0978名前は開発中のものです。
2009/03/29(日) 04:13:27ID:4SqorqSC起きててよかった。
勉強してきます=3
0979名前は開発中のものです。
2009/03/29(日) 07:10:28ID:wuoKvdm5初心者相手に技術自慢したいならc++関係のスレに行けばいいのに。
そこでは相手にもされない程度なのか?
DXライブラリ
0980名前は開発中のものです。
2009/03/29(日) 07:26:38ID:vMEVjIQX俺はCについてはド素人同然なので、いろいろ教えてもらえるのは助かる。
確かにスレ違いではあるんだが、DXライブラリを使ってること前提で
話をしたい場合もあるし。
0981名前は開発中のものです。
2009/03/29(日) 10:08:36ID:BGS9yVjy趣味でゲーム作ってるのが長い人には、Cの書き方でパパーッと書き上げる事もできるし、
(Windows95の頃から始めたような人なら短いものならOOじゃない方がある程度の大きさでも楽だったりするしね。)
3Dに手出す(主にデータ的な部分)のが面倒な人には、
余計なモンついてなくて2Dに特化してるのに、 変な癖が少ないから使いやすい。
あと、最初からゲームパッドとかに対応は何気に使えるし。
車輪の再開発をやってきた様な人には、
ソースもあるからちょっとだけ手を加えたい時とかも 其れが可能で、
わざわざRequestしないで良いのは、時間的にもモチベーション的にも良い選択肢。
初心者にも優しいライブラリだけど、其れだからといって
昔のHSPみたいに、他の言語知ったら使いたくなくなるような不自由さがあるわけでもない。
まぁ、DirectXバリバリつかうぜ!!って人とかには別だろうけど。
0982名前は開発中のものです。
2009/03/29(日) 12:18:31ID:eagJL9bRそれバグでもなんでもねえし、
ポインタのサイズは変わらないだろ
0983名前は開発中のものです。
2009/03/29(日) 13:11:06ID:Zf+/7kJf>>982
正確に書くと、継承した場合のメンバ関数ポインタのサイズが4バイトとは限らない(コンパイラ依存)
多重継承や仮想継承をしている場合、正しいポインタサイズを返すために8バイトや12バイトとなることがある。
しかし、昔のバグコンパイラではこの点が考慮されておらず必ず4バイト固定だった時代があり、派生や仮想関数を呼び出そうとするとアラインメントを調節する必要があった。
ということ。ポインタは必ず4バイトというのは早計だよ。
0984名前は開発中のものです。
2009/03/29(日) 18:18:24ID:eagJL9bR何故得意気なのか理解できんが、
それはサイズが変わるとは言わないだろ?
結局のところ、静的なサイズは確定している。
0985名前は開発中のものです。
2009/03/29(日) 21:00:34ID:aWInPsJ8RTTIしていると大問題。
なんか、微妙にスレ違いだし、
偉そうにしているといわれたようなので黙って老害は去りますね。
失礼しやした。
0986名前は開発中のものです。
2009/03/29(日) 22:56:36ID:8b86AGfHで、次スレはどうするんよ
0987名前は開発中のものです。
2009/03/30(月) 00:07:56ID:Ui9Ndm7F0988名前は開発中のものです。
2009/03/30(月) 01:19:18ID:Y8nEXzvT0989名前は開発中のものです。
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:x1tfO2A20992名前は開発中のものです。
2009/03/30(月) 18:42:02ID:b98OMwXUを使えば起きない
0994名前は開発中のものです。
2009/03/30(月) 18:46:45ID:x1tfO2A2適当な変数にそのフレームで一回押されたか押されてないかを記憶しておけばいいんでは?
main{
int space = 0;
while(うんたら){ //1フレーム間での処理
if (CheckHitKey(SPACE)==1)space=1;
A ;
B ;
C ;
space=0;
ScreenFlip();
}
}
0995名前は開発中のものです。
2009/03/30(月) 19:18:36ID:9Ep+SxhG「ifの処理があるごと」じゃなくて「ChecHitKey」が実行されるごとだけど、
ご想像の通り、1フレームに何回もチェックしてたら
Aでは行われてBでは行われないって事がおきるはずだね。
994さんが言われてるようにフレームの一箇所でだけチェックして記録しておくってのも手だけど、
やっぱり992さんの言われてるGetHitKeyStateAllが俺としてはお勧めかな。
これはこの命令だけで全てのキーの入力情報を記録するから、
フレームの最初に一回やっておけば、あとはそれを参照するだけでいい。
0996名前は開発中のものです。
2009/03/30(月) 20:06:33ID:II/eiBAq>>994
説明サンクス
上手くいきました!
>>995
なるほど、やはりでしたか。
それが原因のバグがでてましたがなんとか除けました。
0997名前は開発中のものです。
2009/03/30(月) 21:58:12ID:9rT9QBj30998名前は開発中のものです。
2009/03/30(月) 21:59:19ID:9rT9QBj30999名前は開発中のものです。
2009/03/30(月) 22:00:03ID:9rT9QBj31000名前は開発中のものです。
2009/03/30(月) 22:00:48ID:9rT9QBj310011001
Over 1000Threadもう書けないので、新しいスレッドを立ててくださいです。。。
レス数が1000を超えています。これ以上書き込みはできません。