ページ 11

データ読み込み中にロード画面を出す方法

Posted: 2010年7月20日(火) 22:48
by シエル
いつもお世話になっております。シエルです。


【質問1】
現在DirectXを使ってゲームを作成しているのですが、
ステージ1からステージ2へ行く際に、ステージ1で使用したデータ(画像など)を破棄して、
ステージ2で使用するデータを読み込ませようとしています。

大した時間ではないのですが、そのデータ読み込み中の際にロード中の画面を出したいと
思っています。

ですが、メインループの中に画像読み込みの処理とロード中の画面を出す処理を
書いているので、結局は画像読み込み処理が終わってからロード画面の処理を
呼び出すことになってしまいます。
何とかして画像を読み込ませながら、ロード中の画面を出す方法はないでしょうか?
ロード中の画面処理は別スレッドを作成して、そちらで処理させるしかないでしょうか?

【質問2】
ゲーム中のスクリーンショットを取るために、フロントバッファの内容をサーフェイスに
コピーして、D3DXSaveSurfaceToFileで保存できるようにしているのですが、
サーフェイスにコピーする時とファイルに保存する際にやはり処理が重いせいか一瞬固まって
しまいます。
どうにかして、少しずつ保存しながらメインループの処理を続ける方法はないでしょうか?
こちらもスレッドを作成して対応するしかないですかね?

2つとも同じような質問ですが、よろしくお願い致します。

Re:データ読み込み中にロード画面を出す方法

Posted: 2010年7月21日(水) 00:48
by Justy
>質問1
 私はロードアニメーションがなければメインに書きますけど、アニメーションさせるなら
テクスチャの読み込みをスレッドで処理しています。

 アニメーション有りで全てメインで書くなら、(60fpsとかの)滑らかなアニメーションさえ
諦めれば幾つかテクスチャを読んでは画面を更新する、を繰り返せばいいだけなので
どうとでもなるはずです。


>結局は画像読み込み処理が終わってからロード画面の処理を 呼び出すことになってしまいます。
 どういう状態なのかよくわかっていないのですが、順番の問題ではないですか?
 メインループの中にそれらを書いたとしても、ロード画面に切り替わってから
読み込み処理すればいいわけで。
 

>質問2
 ファイル出力を伴うのでしょうがないと割り切っていました。
 ただうちの場合一端テクスチャにレンダリングをしてから表示していますので
サーフェイスにコピーする処理はないですね。それでも確かにカクついてます。

 試したことはありませんが多分スレッドにするしかないとは思います。
 とりあえず実際にスレッドにしてみてはどうでしょう?
 あと出力フォーマットも BMPとかあまり複雑な変換がなさそうなのを選ぶとか。

 最悪 D3DXSaveSurfaceToFileを使わず自前でファイルに出力すれば大夫カクつきは
緩和されるんじゃないかな、と思います。

Re:データ読み込み中にロード画面を出す方法

Posted: 2010年7月21日(水) 00:57
by やっくん
こんばんは。
質問1ですが、私は少々面倒ですがロード画面をデータの破棄やデータのロードの間に細かく何度も呼び出して実装しています。
(呼ぶたびに少しずつロード画面の描画するものを変更するため、静的変数などで描画する物を覚えさせておきます)

下にお粗末ですが、自分の方法のサンプルを載せます。

//------------------------------------
IniLoadScreen(); // ロード画面に使う変数や画像の初期化

/***** 以下、ロード *****/
int pic1 = LoadGraph("test1.png");
LoadScreen();
int pic2 = LoadGraph("test2.png");
LoadScreen();
int pic3 = LoadGraph("test3.png");
LoadScreen();
int pic4 = LoadGraph("test4.png");
LoadScreen();

//------------------------------------

static int loadPicNo = 0;

IniLoadScreen()
{
  loadPicNo = 0;
  /* その他いろいろ初期化 */
}

void LoadScreen()
{
  if(loadPicNo >= ロード画面の画像枚数) loadPicNo = 0;

  // picLoadハンドルはどこかで用意しているものとして。
  DrawGraph(0, 0, picLoad[loadPicNo], TRUE);
  loadPicNo++;
}
//------------------------------------

Re:データ読み込み中にロード画面を出す方法

Posted: 2010年7月21日(水) 08:47
by シエル
>>やっくんさん
ありがとうございます。ソース参考にさせていただきます。

>>Justyさん
いつもありがとうございます。

>>アニメーション有りで全てメインで書くなら、(60fpsとかの)滑らかなアニメーションさえ
>>諦めれば幾つかテクスチャを読んでは画面を更新する、を繰り返せばいいだけなので
>>どうとでもなるはずです。

ロード中の画面もアニメーションになっています。滑らかなアニメーションは諦めたくないです。


>>どういう状態なのかよくわかっていないのですが、順番の問題ではないですか?
>>メインループの中にそれらを書いたとしても、ロード画面に切り替わってから
>>読み込み処理すればいいわけで。

ロード中の画面もアニメーションになっており、ロード画面に切り替わってから読み込み処理を
したとしても、読み込みに時間がかかった場合、その時間だけロード中画面のアニメーションが
一瞬止まってしまいます。
市販のゲームはどうやってるんでしょうね。。。


>>試したことはありませんが多分スレッドにするしかないとは思います。
>>とりあえず実際にスレッドにしてみてはどうでしょう?

スレッドにすれば、特に止まることは無かったです。こちらはスレッドで対応するしかなさそうですね。

>>あと出力フォーマットも BMPとかあまり複雑な変換がなさそうなのを選ぶとか。
>>最悪 D3DXSaveSurfaceToFileを使わず自前でファイルに出力すれば大夫カクつきは
>>緩和されるんじゃないかな、と思います。

自前でファイルに出力ですか…さっぱりやり方がわかりません。
自前で対応するのって、画像の形式をしっかり理解していないと厳しいですよね?
全部データをfwriteで書き込むとかですか?
具体的じゃなくていいので、超簡単に方法を説明していただいてよろしいでしょうか?

Re:データ読み込み中にロード画面を出す方法

Posted: 2010年7月21日(水) 11:00
by 御津凪
DirectX では、テクスチャなどのロード(バッファへのアクセス)と描画を同時には行えません。

もし無理やり描画とロードをスレッドを使って非同期で行った場合、大体の確率でフルスクリーン状態の時にフリーズします。
(DX10以降対応グラフィックスカード+DirectX10以降ではそれを回避できる機構が備わっている物がありますが)

市販のゲームでも必ずと言っていいほどロードアニメーションにカクつき、あるいは開始・終了のタイミングで
(PCの性能によりますが)少なくとも一瞬は止まっているはずです。
1ループごとに小刻みに分けたり、ロスの少ない形式にして読み込んだりと、何かしらの努力はしていると思われます。

ロード画面の前後(暗転状態など)、画面に変化がないタイミングで一気にカクつく原因のデータを読み込む方法もありますが、
ロード中画面以外でも読み込んでいるという嘘をすることになります。

一番いいのはアニメーションのフレームレートをゲームのフレームレートより小さく(例えば半分に)して、
次回アニメーションが更新されるフレームごとに1データ処理するように分割するのがいいかと思います。
この時、アニメーション描画の方はフレームスキップ方式で処理するようにすると楽です。
(それでも環境・データによってカクつく場合があります。そこらへんは個別に対処する必要があるでしょう)


スクリーンショットの方ですが、
通常ゲーム画面のカラーフォーマットはXRGBの32ビットなので、いったん IDirect3DDevice9::GetFrontBufferData で取得した後、
スレッドを使って BMPのファイルフォーマットに沿って出力すれば簡単に処理できるかと。
ただし IDirect3DDevice9::GetFrontBufferData 関数は重い処理なのでカクつくことがなくなるわけではありません。

Re:データ読み込み中にロード画面を出す方法

Posted: 2010年7月21日(水) 11:16
by シエル
御津凪さん。ありがとうございます。

確かに市販のゲームでもたまにロード画面でもカクついてることはありますね。
市販のゲームも小刻みに分けて読み込んだりしてるんですかね。
カクついてるほうが逆に読み込んでる感じが出るかなw

アニメーションの方は、小刻みに読み込むようにして対応してみます。
スクリーンショットの方はスレッドでやったら特に問題が出なかったので、
このまま問題が出なければ、スレッドでやりたいと思います。

この辺で解決にしておきます。

ありがとうございました!

Re:データ読み込み中にロード画面を出す方法

Posted: 2010年7月21日(水) 11:17
by シエル
解決し忘れました。すみません。

Re:データ読み込み中にロード画面を出す方法

Posted: 2010年7月24日(土) 01:18
by Justy
 レスが遅くなりました。

 スレッドで画像を生成したり読み込んだりすることはよくあるんですが
今のコードになってからそれが原因で落ちたこと無いですね。
 たまたまなんでしょうかね。

 たしかに同期をとらなければならないところはあるので、スレッドを使っても
普通の PCで 100%完璧に処理落ちをおこさずに処理するのは至難の技かもしれません。
 ものにもよりますがある程度スペックがあるならあまり目立たない程度にまでは
できるんじゃないかと(これが偶然で動いているのでなければ、ですが)。