13a. 裏画面処理をして画像を動かす。
先ほどのちらちらした表示を解消するために裏画面処理をします。
目に見える画面を表画面とし、データの書き換えの作業をする、擬似的な画面を裏画面とします。
裏画面で次に表示すべき画面のデータを計算、処理し、全部処理が終わったら、リフレッシュレートと
合わせて裏画面を表画面に反映させるという作業を行う必要があります。
複雑なようですがプログラムは簡単です。
先ほどのプログラムは全て表画面に描写したり画面をクリアしたりしていましたが、
描画先を裏画面にする関数SetDrawScreenを使います。
SetDrawScreen( DX_SCREEN_BACK ) ; これで描画先を裏画面へ
SetDrawScreen( DX_SCREEN_FRONT ) ; これで描画先を表画面へ
設定します。今回は裏画面を使用するので上を使います。
裏画面というのは計算だけをする領域で、実際にモニタにはうつりませんから、
計算した結果をモニタに表示する必要があります。裏画面のデータを表画面に反映させる関数は
ScreenFlip() ;を使います。
裏画面で描画してはScreenFlipで反映・・ 裏画面で描画してはScreenFlipで反映・・を繰り返す事で
チラチラした画面を解消する事が出来るのです。
↓コピー&コンパイル用サンプルプログラム↓
#include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){ ChangeWindowMode( TRUE ) ; // ウィンドウモードに変更 if( DxLib_Init() == -1 ) return -1 ; // DXライブラリ初期化処理 SetDrawScreen( DX_SCREEN_BACK ) ; // 描画先を裏画面に設定 int i ; for( i = 0 ; i < 300 ; i ++ ) { ClearDrawScreen(); // 裏画面のデータを全て削除 LoadGraphScreen( i, 0, "char.png" , TRUE ) ; //裏画面へ画像を描写 ScreenFlip() ; // 裏画面データを表画面へ反映 } WaitKey(); // 何かキー入力があるまで待つ DxLib_End() ; // DXライブラリ使用の終了処理 return 0 ; // ソフトの終了 }
実行結果
注意)黄色で書かれている文字や線は表示されません。モーションが画像では伝えにくいために書いたものです。
ほら、画面はちらつきませんね。 ScreenFlipがリフレッシュレートに合わせて裏画面を表示してくれているおかげです。
リフレッシュレートにあわせているという事は60ヘルツのモニタの場合は16〜17ミリ秒ScreenFlip関数で処理が
止まっているという事になります。だから今回Sleep関数を使わなくても画像が急に進む事が無かったんですね。
これはうまく描画できているように見えるかもしれませんが、ちょっと欠点があります。
画像が動いている時に、ウィンドウを動かしてみて下さい。動かせないか、動かせたとしてもぎこちないと思います。
ProcessMessage()という処理をしていないからです。
Windowsは沢山のプログラムが同時に動いているOSです。そこで、他のプログラムとうまく連絡を取り合うための関数を呼ばないといけません。
それがProcessMessage()です。これを呼ぶことで、今度はうまくウィンドウが動かせるはずです。試してみて下さい。
この関数は0以外が返って来るとエラーなので、そうしたらプログラムを終了させましょう。
下のサンプルは上のサンプルにProcessMessage()の処理を付け加えただけです。
#include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){ ChangeWindowMode( TRUE ) ; // ウィンドウモードに変更 if( DxLib_Init() == -1 ) return -1 ; // DXライブラリ初期化処理 SetDrawScreen( DX_SCREEN_BACK ) ; // 描画先を裏画面に設定 int i ; for( i = 0 ; i < 300 ; i ++ ) { if(ProcessMessage()!=0) break; ClearDrawScreen(); // 裏画面のデータを全て削除 LoadGraphScreen( i, 0, "char.png" , TRUE ) ; //裏画面へ画像を描写 ScreenFlip() ; // 裏画面データを表画面へ反映 } WaitKey(); // 何かキー入力があるまで待つ DxLib_End() ; // DXライブラリ使用の終了処理 return 0 ; // ソフトの終了 }
実行結果
略
これはゲームプログラムにおいて非常に大事な処理ですが、今のままでは300回ループすると終わってしまいます。
14章でゲームプログラムの基本となる骨格を紹介します。
- Remical Soft -