ページ 11

新・ゲームプログラミングの館の1.8「コードを短く書く 」について

Posted: 2012年3月01日(木) 22:03
by 柏β
こんばんは。
新・ゲームプログラミングの館で細々とゲーム製作の勉強をしている者です。
1.8「コードを短く書く 」について疑問点がある為、質問させて頂きます。

裏画面に描いた内容を表画面に反映する処理を短く書かない場合、ループ内で以下の順番で処理しています。
引用ですが以下の処理順(関数の実行順)です。

1.画面に描画した内容を消す(ClearDrawScreen関数)
2.画像を描画する(DrawGraphなど...)
3.裏画面に描いた内容を表画面に反映する(ScreenFlip関数)

一方、短く書く場合にはWhileの条件式として上記の処理を順番に行っている(と思う)のですが、その実行順が以下であるという認識です。

1.裏画面に描いた内容を表画面に反映する
2.画面に描画した内容を消す
3.画像を描画する

以下、実際のソースの一部です。

コード:

 
// while(裏画面を表画面に反映, メッセージ処理, 画面クリア)
while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 ){
         MenuDraw();	//メニュー描画
 }
 
仮にこの実行順で処理されているとすれば、ScreenFlipの後にClearDrawScreenをしている為、画面には何も表示されないのでは? と思っています。
実際に実行すると、きちんと画像が表示されるので、この考えが間違っているのは確かなのですが、何故上記の処理で正常に描画が行われるかが分からない状態です。この疑問を解決したく、質問させて頂きました。
もしかしてClearDrawScreenというのは、裏画面に対してのクリア(というよりはSetDrawScreenで指定した先の画面のクリア)という事なのでしょうか……?

あとこれは余談なので無視して頂いても構わないのですが、、、
以下のように、Whileの条件式でのScreenFlip関数の実行をやめ、ループ内でZキーが押された場合にScreenFlip関数の実行を行うようにしました。この場合、Zキー押下後に描画は行われるのですが、キー押下後0.5~1秒程してから描画されます。
キー押下後、すぐに描画されると思っていたのですが、何故こうなるのでしょうか?

コード:

 
// while( メッセージ処理, 画面クリア)
while( ProcessMessage()==0 && ClearDrawScreen()==0 ){
         Keyboard_Update();	//キーの入力状態を記録
    MenuDraw();	//メニュー描画
	if (Keyboard_Get(KEY_INPUT_Z)) {
		ScreenFlip();
	}
 }
 
アドバイス頂ければ幸いです。

PS:一文字の名前が禁止されている……!!
   最後に投稿したのが2,3年前くらいですので、ちょっとビックリしました...w

Re: 新・ゲームプログラミングの館の1.8「コードを短く書く 」について

Posted: 2012年3月01日(木) 22:22
by jay
恐らくですが

ClearDrawScreen関数は"この時点で描画されているものだけを消す"
ScreenFlip関数は"裏画面に描いた内容を表画面に反映するだけ"
なのだと思います。

つまりScreenFlip関数で裏画面の物を反映しても、まだ描画されていないのでClearDrawScreen関数の影響を受けず
その後DrawGraph関数等で描画(表示)することが出来る、ということだと思います。


後半部分については、申し訳ないですが分からないです(汗)

Re: 新・ゲームプログラミングの館の1.8「コードを短く書く 」について

Posted: 2012年3月02日(金) 03:39
by MoNoQLoREATOR
ClearDrawScreen()・・・関数ですか?
ClsDrawScreen()関数のことだとしてお答えします。
この関数によってクリアされる画面は、お察しの通り、SetDrawScreen()関数で指定した画面です。
すなわちこの場合は裏画面がクリアされるわけです。
よって表画面は影響を受けません。

Zキーをしばらく押していないと反応がない件についてですが、デフォルト設定のままだとScreenFlip()関数を呼んだ際、内部ではFPSにタイミングを合わせて処理が行われるので、この関数から脱出するまでに少し時間がかかります。
このタイムラグの後、プログラムの始めにループし、キー入力がチェックされ、その次のScreenFlip()関数でまたタイムラグが発生するため、けっこう遅れることになります。

Re: 新・ゲームプログラミングの館の1.8「コードを短く書く 」について

Posted: 2012年3月02日(金) 07:13
by beatle
MoNoQLoREATOR さんが書きました:ClearDrawScreen()・・・関数ですか?
ClsDrawScreen()関数のことだとしてお答えします。
ClearDrawScreenはれっきとしたDXライブラリの関数です。
参考:ClearDrawScreen

Re: 新・ゲームプログラミングの館の1.8「コードを短く書く 」について

Posted: 2012年3月02日(金) 07:28
by beatle

コード:

#include <DxLib.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    ChangeWindowMode(TRUE);
    DxLib_Init();
    SetDrawScreen(DX_SCREEN_BACK);

    int chara_handle = LoadGraph("images/character01.png");
    while (ProcessMessage() == 0 && ClearDrawScreen() == 0)
    {
        DrawGraph(100, 100, chara_handle, TRUE);
        if (CheckHitKey(KEY_INPUT_Z))
        {
            ScreenFlip();
        }
    }
    DxLib_End();
}
こんなコードで実験してみたところ、Zキーを押した瞬間にキャラクタ画像が描画されました。
Menu関数の中身などが分かりませんからなんとも言えませんが、一応報告まで。

Re: 新・ゲームプログラミングの館の1.8「コードを短く書く 」について

Posted: 2012年3月02日(金) 09:17
by softya(ソフト屋)
ClearDrawScreenは裏画面のクリアですね。
ScreenFlip();は裏画面を表画面にひっくり返します。
なので、(というよりはSetDrawScreenで指定した先の画面のクリア)の認識で合っています。

もう一つのコードは、ZKeyをおせばすぐ反映されるはずです。
と言うより押すまで画面は書き換わらないはずですが。

Re: 新・ゲームプログラミングの館の1.8「コードを短く書く 」について

Posted: 2012年3月02日(金) 09:20
by 沖 滉均
MoNoQLoREATOR さんが書きました:ClearDrawScreen()・・・関数ですか?
ClsDrawScreen()関数のことだとしてお答えします。
念のため、ClsDrawScreenは内部でClearDrawScreenを呼んでいます。
ClsDrawScreenは昔の定義ですね。
Ver.2.2aでClearDrawScreenに変わっているので実質同じものです。(コンパイルはどちらでも通ります)
オフトピック
というか、置き換えられたのはもう6年くらい前なので知っている方が不思議なのですが…
現存のマニュアルやここの館でも見つからないような気がしますが…

Re: 新・ゲームプログラミングの館の1.8「コードを短く書く 」について

Posted: 2012年3月02日(金) 14:54
by MoNoQLoREATOR
>> 沖 滉均さん
私が使用した参考書が大変古いものだからですね。
確認したところ、2006年に発行されたものでした。
まだVistaが出ていなかった頃・・・ですかね。時代を感じますね。

Zキーについてですが、考え直してみるとおかしいですね。
ScreenFlip()関数から脱出するまでに少し時間がかかると言っても60分の1秒ですし、それが原因なら相当PCが重い状態だったということになりますよね。
キー情報を取得してからScreenFlip()関数が呼ばれるまでに相当重い処理をしているとしか考えられませんね。

Re: 新・ゲームプログラミングの館の1.8「コードを短く書く 」について

Posted: 2012年3月02日(金) 20:42
by 柏β
みなさん、ご回答ありがとうございます。

ClearDrawScreen関数により、表画面ではなく裏画面の内容がクリアされる事が分かり、納得いたしました。

1.裏画面に描いた内容を表画面に反映する
2.画面に描画した内容を消す
3.画像を描画する
4.裏画面に描いた内容を表画面に反映する
5.画面に描画した内容を消す




余談で記載した内容ですが、私の環境ではやはりZキー押下後に少し間をおいてから描画されます。
beatleさんが検証してくれたソースでも試してみましたが、やはりキーを押下した瞬間ではなく、少し間があってから描画されるようです。
とりあえず、普通にゲーム製作を行う分にはこのような記述はしないと思いますので、この件については気にしない事とします。
ちなみに、whileの条件式のClearDrawScreen関数の処理を削除した状態で実行すると、Zキーを押下したと同時に描画されました。
一応検証したソースを載せておきます。

コード:

while(ProcessMessage()==0) {
	Keyboard_Update();	//キーの入力状態を記録
			
	if (Keyboard_Get(KEY_INPUT_Z)) {
		MenuDraw();	//メニュー描画
		ScreenFlip();
	}
}

Re: 新・ゲームプログラミングの館の1.8「コードを短く書く 」について

Posted: 2012年3月02日(金) 23:32
by Dixq (管理人)
館のサンプルでは ScreenFlip(); で垂直同期を待っているので、特に何も考えなくても
そのままループすればほとんどの場合60FPSになります。
しかし、検証されたソースはScreenFlipを通らない可能性があるので、
その場合待機する処理が無く、すごい速さでループするものと思います。

# また、ClsDrawScreenについてですが、昔々ゲームプログラミングの館にはこの関数が書かれていました。
# 今は互換性を持たせるためだけに残っている関数だと思います。

> PS:一文字の名前が禁止されている……!!
>   最後に投稿したのが2,3年前くらいですので、ちょっとビックリしました...w

よければ使えなかったお名前を教えて頂けないでしょうか?

Re: 新・ゲームプログラミングの館の1.8「コードを短く書く 」について

Posted: 2012年3月03日(土) 01:25
by 柏β
>よければ使えなかったお名前を教えて頂けないでしょうか?

使えなかった名前は「柏」です。
よくよく見ると、他のトピックに「白」さんという名前で投稿されている方がいらっしゃるようですので、私の勘違いかもしれません……。

Re: 新・ゲームプログラミングの館の1.8「コードを短く書く 」について

Posted: 2012年3月03日(土) 01:29
by Dixq (管理人)
調べてみましたが、柏さんのお名前での登録は無いので、登録可能だと思います。
もし出来ない場合は対応しますので、お伝え下さい。
# また既にご登録済みでパスワードがわからない場合は再発行致します。

Re: 新・ゲームプログラミングの館の1.8「コードを短く書く 」について

Posted: 2012年3月04日(日) 22:32
by 柏β
すいません、個別の連絡方法が分からなかったので、こちらで回答します。

再度試してみましたが、掲示板及びmixC++どちらとも、2文字以上の名前は受け付けてくれないようです。
掲示板ではプレビュー及び送信ボタン押下時にエラーとなります。
mixC++の登録では、名前を入力してテキストボックスからロストフォーカスした時点でエラーになります。そもそも2文字以上はダメですと注意書きがありました...
その為、mixC++には「柏-12」の名前で過去に登録済みです(申し訳ありません、登録していたのを忘れていました)
パスワードは覚えている為、大丈夫です。

1文字の名前も許可して頂けるとありがたいですが、私的には現状(2文字以上)でも構いません。
要望が多ければ対応などでもよいと考えています。