DXライブラリ 総合スレッド その19 [無断転載禁止]©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
Cを習得した程度のスキルでも、ゲームのグラフィックを比較的容易に描画する事のできる、
「DXライブラリ」に関するスレッドです。
DXライブラリに関するテクニックなどの情報交換などを行う事で、
多くのDXライブラリユーザのスキルの向上に役立てたら幸いです。
【公式】
http://homepage2.nifty.com/natupaji/DxLib/
【関連スレ】
C/C++ゲーム製作総合スレッド Part7 [転載禁止](c)2ch.net
http://peace.2ch.net/test/read.cgi/gamedev/1420939171/
ゲームプログラムなら俺に聞け32(c)2ch.net
http://peace.2ch.net/test/read.cgi/tech/1441693570/
●DXライブラリではなくDirectXの質問ならこっちへ
【C++】 DirectX初心者質問スレ Part39 【C】 [転載禁止](c)2ch.net
http://peace.2ch.net/test/read.cgi/tech/1418438785/ char binadata[10000000]ってやったらエラーが出た
char binadata[9000000]だったら大丈夫だった
char binadata[10000000]でもグローバル変数だったら大丈夫だった
なんでグローバル変数だと大丈夫なん?
使うメモリの容量がローカル変数とグローバル変数では違うの? ローカルメモリはスタックメモリに配置されるからって
大学でならわなかったかい? エラーってstack overflow?
初歩的すぎる 記憶域でのスタックと静的領域とヒープの3つを理解し
適切に使い分けられなければ
蹴り入れられても文句言えない
C言語入門からやり直すべきよ やり直すというより、>>8は現在進行形のC入門者なんだと思う ttfファイルを読み込んで使ってるんだけど、あらかじめ同じフォントがインストールされているとサイズがおかしくなる
どうにかならない? LoadFontDataToHandle関数で解決しました 今更だけどこれって
「ディーエックスライブラリ」?
「デラックスライブラリ」?
前者で読んでるけどどっちなんだ もともと DirectX のDXだからディーエックスでいいんじゃない ここで聞いていいのか分かりませんが
14歳からはじめるC言語わくわくゲームプログラミング教室 Visual Studio 2013編のP105に
もし複数のキーが同時に押された場合、GetJoypadInputState関数は押されたキーを表す定
数を合計した数値を返します。たとえば←と↑が同時に押された場合、PAD_INPUT_LEFT(実
体は整数の2)とPAD_INPUT_UP(整数の8)の合計(つまり 10 )が返さます。キーを表す定数
には2進数で表すとビットが重ならない数値が割り当てられているので、合計してもキーを表す
ビットの状態は変わりません。
←↑の同時押し ↑→の同時押し
0000 0010(2) 0000 1000(8)
+0000 1000(8) +0000 0100(4)
──────── ────────
0000 1010(10) 0000 1100(12)
とあるんですが、テンキーって
789
456
123
だから
↑8
←4 →6
↓2
になって、←↑の同時押し:4+8=12、 ↑→の同時押し:8+6=14だと思うんですが、DXライブラリでは
↑8
←2 →4
↓6
になるんでしょうか? >>18
多分その書籍は「同時押ししても別々に認識できる」
というのを示したかっただけな感じがするので
実際の割当がどうなっているのかはあまり気にしなくていいと思います
あと、テンキーの数字と割当整数がそのまま対応しているわけではないです その数字のままだったら、2+4と6単体と区別つかないだろう
2進数慣れといたほうがいいよ 皆さんありがとう
この部分の前後読んでもさっぱり分からないので
これ以上気にしないで先に進むことにします
この先具体例が出て来るかも知れませんしね ビット演算調べて。
一桁目が1 0001 1x1=1
二桁目が1 0010 1x2+0=2
三桁目が1 0100 1x2x2+0x2+0=4
四桁目が1 1000 1x2x2x2+0x2x2+0x2+0=8
2になると一桁上がるから2進数。
普通の10進数も、例えば、1234は
=1x10x10x10+2x10x10+3x10+4
一つのキーが押されているか押されていないかを表現するのには0と1で充分。
つまりキーが4つなら0000から1111で表現できる。
キーの組み合わせはビットのor演算になる。
2進数だから足し算と結果は同じになるけど。
逆に一つのキーの状態を調べるのはandで。 こうして見てると、ビット演算を他人に教えるって結構大変そうだな ビット演算の話なのか?
俺はてっきり
if( GetJoypadInputState( DX_INPUT_PAD1 ) & PAD_INPUT_UP )
みたいに識別子と論理積を使って判定するのではなく
if( GetJoypadInputState( DX_INPUT_PAD1 ) == 8 )
みたいにその数字で直接入力判定してるから、テンキーの割り当て整数を知りたい
っていう話をしているのかと思ったんだけど とりあえず、入力状態を調べる関数の返り値を2進表記文字列と10進表記文字列で対にして画面左上に表示するだけの簡単なアプリ作っても良いかと思う。
と、ここで気になって調べたら、2進文字列への変換は
Cはitoa←VCでしか使えない? 今回は使えるかな
C++はstd::bitset
簡単なはずなのに、簡単でない気がしてきた。
用途限定なら自作した方が楽な(学べる)気もする。 >if( GetJoypadInputState( DX_INPUT_PAD1 ) & PAD_INPUT_UP )
&(and)だから特定の一つのキーが、押されているかのチェック
押されていなければ0、つまり偽 FALSEになりif以降は実行されない。
押されていれば0以外 真となりifは実行される。
if ((GetJoypadInputState(DX_INPUT_PAD1)&PAD_INPUT_UP) !=0)
これが省略されているのが一行目。
0であるならば、0以外であるならば、機械は基本たったこれ2つの判断で分岐する。!=0は0でないなら、の意味。not イコール 0
while(1)とかも同じ考え方。これは条件が常に真(偽(0)ではない)なので無限ループになる。
for(初期化(が多い);継続の条件;条件が真なら行うこと)
いずれ条件が偽になるからこそ使えるということ。
>if( GetJoypadInputState( DX_INPUT_PAD1 ) == 8 )
というかね、それならまだ
if(GetJoypadInputState(DX_INPUT_PAD1)==(PAD_INPUT_UP|PAD_INPUT_LEFT))
こういう例をあげてくれたほうが嬉しかったかな。
|を+にかえても思ったとおりに動作はするかも知れないが、それではいけないということ。 if(GetJoypadInputState(DX_INPUT_PAD1)&(PAD_INPUT_UP|PAD_INPUT_LEFT))
にしないと使えないね。
寝ます。 ごめんこれも使えなかった。
同時に押された判定はすこし長くなるな。
このままではどちらか片方押さた場合でも、、、
眠い。ほんと寝ます。 if(GetJoypadInputState(DX_INPUT_PAD1)&(PAD_INPUT_UP|PAD_INPUT_LEFT)==(PAD_INPUT_UP|PAD_INPUT_LEFT))
一つのキーチェックは!=0でいいけど
ボタン1|ボタン2|ボタン3
とか複数キーが押されているかのチェックの場合は駄目ですね。一つのキーが押されただけでも!=0を満たしてしまうから。
連投すいません。そして初級者以外の方、失礼しました。 if((GetJoypadInputState(DX_INPUT_PAD1)&(PAD_INPUT_UP|PAD_INPUT_LEFT))==(PAD_INPUT_UP|PAD_INPUT_LEFT))
すいません。もう一度だけ。
c 演算子 優先順位 で検索してください。
確か&(アドレスじゃない方)は==よりあとに評価された気がする。これはCの欠陥ではないのかとか書いてた書籍があった気がする。
不安だし、()はつけといたほうが良いと思う。 なぜ俺が適当に上げた例に対して
何レスにも渡って解りづらい解説をしているのだ・・・
というか肝心の>>18はもう居ないっぽいから
質問したかった内容自体がそこで合ってるのかわからんぞ これでも簡単に書こうとしたのですけどね。
どの辺がわかりづらいですか?
簡単なことを簡単に書くのは難しいですね。 >>33
説明が長くなるほど要点をつかみづらくなるから
補足は少なく、説明の訂正は出ないようにして、
大事な部分だけ短く簡単に説明した方が初心者には理解しやすい
補足とかは質問者に求められたときだけ説明すればいいかと DXLibは初心者向けって聞くけど、シャープDXなどと何が違うの?
2Dゲームの場合。3Dなら素直にUnity使うし シャープDXってなんぞ。
初心者にオススメの1つではあるが、これで作られた市販ゲームもあるくらいには幅広いよ C言語で書きたくてwindowsAPI、グラフィックAPI触りたくない人向け 確かにC++ぽく作られてないのは嬉しい。
他の人のソースコードとかが解読しやすい。 俺もライブラリ作ってやるぜ!と意気込んで、
グラフィックと入力と音周りが出来たあたりで、DXライブラリで良いんじゃね?と気づいて戻ってくる感じ キャラクターIDをソートする場合なんですけど
こういう場合はやっぱりバケットソート的なアルゴリズムが最速なのでしょうか?
条件
・10000体のキャラクターがいる(ID0〜ID9999)※ID0番は空欄扱いの時に使うので実質9999体
・それぞれのキャラクターはスコアを持ってる(とりうる値はunsigned charの0〜255)
・ソートする時はスコアの低い順に並べる
・スコアが同点ならIDが若い順に並べる
自作した処理の概要
int baketu[10000*256];
int kekka[10000];
まず配列baketu[]を0クリアして
for(int ID=1;ID<10000;ID++){
baketu[(IDのスコア*10000)+ID] = ID;
}
int x=0;int i=0;
while(x<9999){
if(baketu[i]>0){kekka[x]=baketu[i];x++;}
i++;
}
こんな感じです
int baketu[10000*256] ←なんかこれで10メガくらい使うみたいですし
もっとスマートなやり方は無いものでしょうか?
ただ、かなり頻繁に呼ぶ処理なので最優先したいのは速度です 普通にクイックソートでいいのでは
ソート時間の比較
http://www.ics.kagoshima-u.ac.jp/~fuchida/edu/algorithm/sort-algorithm/speed-compare.html そもそも頻繁に呼び出すなら
いちいちソートしないでソート結果をずっと保持する。
オブジェクトの追加削除が頻繁なら、
ソートではなく、正しい位置に差し込むようにする。 RPGなどのスクロールゲーは、描画可能画像(マップサイズ)を作ってそこに描画した後に、ウィンドウに描画すればいいのですか?
速度やメモリを考えると、やめた方がいいですかね >>43
スコアの変更をするたびに並び替える関数を呼ぶってことでしょうか
その場合は一般的なソートではなくて、条件が限定されてる場合ならではの最適解があると考えて間違いないですよね?
あと今思ったんですけど>>41の処理って下記の処理と速度ほとんど変わらない…?
int kekka[10000];
int x=0;
for(int i=0;i<256;i++){
for(int ID=1;ID<10000;ID++){
if(IDのスコア==i){
kekka[x]=ID;
x++;
}
}
} どっちも2,560,000ループだから変わらないね。
可読性なら、俺は45のほうが解りやすかった。
(というか45を読んでようやく41がなにをしたいのか解った)
スコアの変動幅が少ない(=順位の変動が少ない)なら、
スコアが変わるたびに前後のスコアと比較して入れ換えるやりかたでもいいかな
スコアが頻繁に変わるなら
数秒毎にまとめてquicksort >>44
何が言いたいのか分からんが
ウィンドウより気持ち広めに描画すればいいんじゃないの? フレームレートを上げてゲームの進行の高速化をしたいけどどうすればいいの?
setgraphmodeの第4引数に値をぶっこんでも何も起きん > 画面モードを設定する
> int SetGraphMode(int ScreenSizeX,int ScreenSizeY,int ColorBitDepth,int RefreshRate=60)
> 戻り値
> DX_CHANGESCREEN_OK 画面変更は成功した
> DX_CHANGESCREEN_RETURN 画面の変更は失敗し、元の画面モードに戻された
> DX_CHANGESCREEN_DEFAULT 画面の変更は失敗しデフォルトの画面モードに変更された
> DX_CHANGESCREEN_REFRESHNORMAL 画面の変更は成功したが、リフレッシュレートの変更は失敗した
とりあえず戻り値の確認しとけ。
あとはフレーム管理をどうやってるかによると思う。
垂直同期に丸投げしないで自前でフレーム管理してるなんてオチは……流石にないか ゲームループを秒間60回さなくても高速処理できちゃうの?
元より軽く作って、普段はウエイト入れてるだけにしないといけないんじゃないかな。 >>53
何を疑問に思ったが知らんが、最初からそういう話じゃねぇの >>52
thx。クソ速くなりました
しかしSetWaitVSyncFlagの変更はDxLib_Init前でないと利かないようです
起動中に進行速度を自由に調整したかったのですが難しそうです いやだからフレーム管理方法なんて複数あるんだから
使い分ければいいじゃない >>55
頭はゲームの内容を考えることに使った方がいいと思います >>54
すいません、今自分で作っているモノが何をしても60フレームで安定しているものですから、逆の意味で頭を抱えていたんです。
で、>>52氏の教えに従いVSYNCを外したら2000前後を叩きだしたので、>>51氏の最後の隠しパラメータRefreshRate=60の意味が分かりました。
本当にありがとうございました状態ですm(_ _)m
初挑戦で5年ばかり仕様に気が付かないとか、ちょっと笑えます(^^; 今更だけど、リフレッシュレート変えるのはアカンだろw
垂直同期もオフにすんなw
根元でフレーム間の時間経過を定数倍するとか、
更新処理を複数回呼ぶとかいろいろやり方あるだろが >>60
一般に、60決め打ちとかのほうが
初心者には作りやすいと思うぜ >>61
そういう原始的な作りでも更新処理を複数回呼べばいいだけだし・・・
まあ入門サイトにありがちな経過フレーム数を1とする可変更新方式はゴミなんで
さっさと止めたほうがいいと思うよ 固定するならタイマー管理なのかねぇ
最近は120Hzとかのモニタも珍しくないし
>入門サイトにありがちな経過フレーム数を1とする可変更新方式
どんなん? 俺も垂直同期切ってタイマー管理だな
75ヘルツのモニターで早送りになった経験があるから 固定更新のために垂直同期切ってタイマー管理はありだけど
ティアリングが気になったりしない?
>>62はちょっと分かりにくかったかな
要は垂直同期をとりながら更新をカウントしてるようなタイプね
メジャーなところだと龍神録とか
この方法は環境の違いを直接受けるし、その対処も醜くなるんだよ 固定にするなら、リフレッシュレート制御かテアリングか
どっちかを取るしかないんじゃないの?
>カウント
龍神録ちろっと見てみたけど分からんかった
単位時間あたりのループ回数をチェックして、それ超えそうになったらウェイト入れる感じ? 2フレームに一度スクリーンフリップをすることでゲームの進行速度が2倍になりました
ゲーム中に速度の変更がきくようになったので目的は達成し解決しました ttp://gameprogrammingpatterns.com/game-loop.html#play-catch-up 垂直同期でやってるけど何故かFPSが59.9が多いんだよな
偶に60いくんだけど。龍神録のFPS管理は何故か57FPSになる もともとNTSCの垂直同期って59.94Hzだけど
今のは完全に60Pなんかね 龍神録のところのプログラムって、垂直同期とタイマー待機を同時にやってた気がする
どっちかだけにするといいはず >>70
だからか、東方だと60FPSが多いからなんでだと思ってた
>>71
龍神録のタイマー待機関数をSleepからWaitTimerにしたらいくらかマシになったけど
なぜか垂直同期を切ってFPS制御するより垂直同期とFPS制御を同時にやった方が軽くなった LoadGraph等で同じ画像を複数回読み込んだときは、やはり同じ画像が複数個分メモリに展開されるのだろうか? 画像を改変したりして複数いるなら1回読み込んで、コピーするべき
HDD等からの読み込みは遅いから 垂直同期切ってもウィンドウモードだと60fpsになっちゃうんだけどこれどうにかならない? 仮想関数の呼び出しが遅い
最初はDXlibと関係あるのかなーと思ったけどC++の仕様っぽい
みんなも気をつけろ 自分も聞いたことあるけど、それがクリティカルになるって、
他のところがボトルネックになってたりしない?
あとは最適化オプションとかで何とかなりそうではあるが 関数の呼び出し速度が気になるようじゃ元々が問題だと思うんだけど
実際に通常関数を呼ぶのと速度的にはどれくらいの差なんだろう 3Dモデルのボーンをプログラムで動かすときに、
・ボーンをワールド座標の特定の場所を向くようにしたい(カメラの注視のようにボーンを一点に向けたい)
・ボーンをワールド座標の特定の角度にしたい。例えば、ボーンを水平な角度にしたい
を行いたいのですが、
ボーンを動かすのは MV1SetFrameUserLocalMatrix でローカルの変換行列を指定する方法しかないですが
どうやればできますか? プログラムをステップ実行したときに
DXライブラリのソースにステップインするにはどうやればできますか?
Visual Studio 2013使ってます ちなみにDXライブラリのソースにステップインしたい理由は
エラーコードが-1しかなくて、何が原因かわからなくて調べるためです
たまに挙動不審になったときの調査もしたいです 自己解決した時は、どんなに簡単であってもその方法をだな その方法も何もDXライブラリのソース公開されているからlibファイルの代わりにソースをプロジェクトに追加するだけやん pdbを置くだけでしょ
ステップインしたらその時にソースの場所聞いてくるわ という風に、人によってやり方違うので
どんなに簡単でも手順は書いておいたほうが
それが質問した人の礼儀かと
レスしようとして自分とこで検証して回答しようとしたら
自己解決しましたの一言でしまってたりすること多いしねえ pdbって使い道あったのか
いつも使い道分からずに放置してたわ DXライブラリは3Dモデルの大きさをセンチメートルで管理するのがいいのか?
メートルで管理してカメラの Near Clip を小さくするとアウトラインやZTestがおかしくなる 単位は人それぞれだけど、精度を下げりゃ描画が甘くなるのはそりゃ当然よ Zバッファのビット深度を変更する関数があったような
デフォは16bitだから32bitとかにしてみては >>90
俺も以前同じようなことで悩んだわ
Near Clipは破綻しない程度に大きな値をとる必要があるとのこと
俺の場合は1メートル〜数万キロのレンジで幅が広すぎて単位をどう弄ろうがZバッファの深度を深くしようがダメだったんで、
ここで教えてもらった「ワールド空間を複数の距離レンジに区切ってそれぞれを描画し最後に合成する」手法で切り抜けた
おかげでカメラが物体から5メートルまで寄ろうが1万キロ離れようがあまり問題はなくなった
ただし代償として描画処理の負荷は上がったけど・・・
>>92
SetZBufferBitDepthでZバッファの深度を変えられる
でも確か24ビットまでじゃなかったかな? >>91-93
レスありがとうございます
SetZBufferBitDepthは簡単なのですぐに試してみます
「ワールド空間を複数の距離レンジに区切ってそれぞれを描画し最後に合成する」手法は
ちょっと簡単にはできなさそうですが、プロのゲームっぽいですね。すごい >>94
方法さえ教えてもらえればそんなややこしい実装じゃなかったよ
1. まずMakeScreen関数で合成用のサブ画面を作る
2. SetDrawScreen関数で作成したサブ画面を描画対象にしてその後カメラのパラメータを設定
3. SetCameraNearFar関数でカメラから一番遠いクリップ領域を指定
4. ワールド空間の物体を描画
5. SetDrawScreen関数で裏画面を描画対象にする
6. DrawGraph関数で合成用サブ画面に描いたグラフィックを裏画面に投下処理つきで描画
7. 2〜6をクリップ領域を1つずつ手前に近づけながらforループで必要回数だけ繰り返す
8. ScreenFlip関数で裏画面と表画面を切り替える
みたいな感じ
継ぎ目がちょっと気になるという欠点があるらしいけど、俺の作ったプログラムでは大して問題にはならなかった >>95
ありがとうございます。実装できる気がしてきました すいません。 初歩的なことを教えて下さい。
DXライブラリを3.12aから3.16d(最新版)に昨日上げたのですが、以下の様なエラーが出ます。
エラー 1 error LNK1104: ファイル 'DxDrawFunc_vs2012_x86_d.lib' を開くことができません。
丁度ドライブが一杯になったのでそれでファイル欠損起こしたのかと、整理して落としなおして
再インストールしても変わりません。 消さないでいた3.12aに戻せば正常にコンパイルできます。
どんなポカミスが考えられるでしょうか。 DXライブラリのフォルダの下を 'DxDrawFunc_vs2012_x86_d.lib' で検索して、
そのフォルダがプロジェクトのプロパティの「リンカー」の中の
「追加のライブラリディレクトリ」に設定されているか確認してみたか?
設定してなかったら設定する ありがとうございます。
おっしゃるとおりでした。
C/C++全般のインクルードディレクトリだけ変更してリンカ全般の追加を変更していなかったのが原因でした。
これで総て正常終了できました。
ありがとうございました。 DrawBox()って思った以上にコスト高なのね。
エディタ作っているのですが、マウスで指定範囲を決定するのに半透明のFilling=TRUEで
サイズが{400,200}程度になると追いついて来ないし。うちの環境だと。
まあ範囲が分かれば良いだけなので、非透明のFilling=FALSEにしましたが。
機能の根幹に必要な命令じゃなくて良かった・・・。 ■ このスレッドは過去ログ倉庫に格納されています