ゲーム制作講座2

2.絵を動かそう


 絵を動かして見ましょう。とりあえず絵が左から右へ動くプログラムを考えます。
 ここでふと考えてみましょう、どうやったら絵が動いているように見えるか!
答えは簡単、アニメの手法を拝借させていただきましょう。
 アニメの絵は個々がすべて違う紙(セル)に描かれた独立した絵です。でも人はそれを短い間隔で
次々と絵をすり替えられるとあたかもその絵が動いているように見えます

実はTVゲームでも同じ様な手法が使われています。ここでも早速やってみましょう。

 最初に一番左上に絵を表示します。次に少し右にずれたところに絵を表示します。
次はそこからさらに右にずれたところに絵を表示します。
 要はこれをずっと繰り返せば良いわけです。

 あと絵と絵を表示する間隔を決めなければ一瞬ですべての絵が表示されてしまい、動いている
ように見えません
。とりあえず一枚絵を表示するごとに20分の1秒待つことにしましょう。

そんなこんなで出来たのが次のプログラムです。

( 尚、使っているグラフィックファイルは『test1.bmp』となっていますが、グラフィックはどんな
ものでもかまいませんので、実行する際は適当なグラフィックを用意してください。)
#include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { // DXライブラリ初期化処理 if( DxLib_Init() == -1 ) return -1 ; // 一番左上に絵を表示 LoadGraphScreen( 0 , 100 , "test1.bmp" , FALSE ) ; // 20分の1秒待つ WaitTimer( 50 ) ; // 少し右にずらして絵を表示 LoadGraphScreen( 10 , 100 , "test1.bmp" , FALSE ) ; // 20分の1秒待つ WaitTimer( 50 ) ; // 以下同文(?) LoadGraphScreen( 20 , 100 , "test1.bmp" , FALSE ) ; WaitTimer( 50 ) ; LoadGraphScreen( 30 , 100 , "test1.bmp" , FALSE ) ; WaitTimer( 50 ) ; LoadGraphScreen( 40 , 100 , "test1.bmp" , FALSE ) ; WaitTimer( 50 ) ; LoadGraphScreen( 50 , 100 , "test1.bmp" , FALSE ) ; WaitTimer( 50 ) ; LoadGraphScreen( 60 , 100 , "test1.bmp" , FALSE ) ; WaitTimer( 50 ) ; LoadGraphScreen( 70 , 100 , "test1.bmp" , FALSE ) ; WaitTimer( 50 ) ; LoadGraphScreen( 80 , 100 , "test1.bmp" , FALSE ) ; WaitTimer( 50 ) ; LoadGraphScreen( 90 , 100 , "test1.bmp" , FALSE ) ; WaitTimer( 50 ) ; LoadGraphScreen( 100 , 100 , "test1.bmp" , FALSE ) ; WaitTimer( 50 ) ; LoadGraphScreen( 110 , 100 , "test1.bmp" , FALSE ) ; WaitTimer( 50 ) ; LoadGraphScreen( 120 , 100 , "test1.bmp" , FALSE ) ; WaitTimer( 50 ) ; // キーの入力待ち WaitKey() ; // DXライブラリ使用の終了処理 DxLib_End() ; // ソフトの終了 return 0 ; }
 どうでしょう。なんとか動いているように見えるかと思います。
 ここで時間を待つために使われている関数 WaitTimer は、一つの整数型の数値を引数に取る関数で
処理を止める時間をミリ秒(1000分の1秒)単位で指定することが出来ます。上記のプログラムで 50 ミリ秒
待つようにセットしてあるのは20分の1秒が 1000 / 20 = 50 、つまり50ミリ秒のことだからです。

 なお上のプログラムは繰り返し同じようなことをしているので、for 文を使って次のように表現することが
出来ます。for 文を使ったほうが断然プログラムがすっきりします。

#include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { int i ; // DXライブラリ初期化処理 if( DxLib_Init() == -1 ) return -1 ; // 一番左上に絵を表示、20分の1秒待つ、を13回繰り返す for( i = 0 ; i < 13 ; i ++ ) { // 絵を表示、絵を描くX座標は i が1増えるごとに10ドットづつ右にずれてゆく LoadGraphScreen( i * 10 , 100 , "test1.bmp" , FALSE ) ; // 20分の1秒待つ WaitTimer( 50 ) ; } // キーの入力待ち WaitKey() ; // DXライブラリ使用の終了処理 DxLib_End() ; // ソフトの終了 return 0 ; }
<実行例>

 さて、どうにか動いているように見えるプログラムが組めましたが、上の図を見てもわかるように
今のままでは描いた絵の端がすべて残ってしまっているのでとても見苦しくなっています。

 そうです、一度画面に何かを描いたらちゃんと消さなければなりません。どうしましょう。

 と、そんな時に登場するのが ClearDrawScreen 関数です。
 この関数は画面に描いてあるグラフィックを全部消してくれます。とにかく消します。否応無しに
消します。そしてただ消すだけの関数です。便利です、使わない手はありません。

 そんなわけで ClearDrawScreen 関数で画面をその都度消すようにしたのが次のプログラムです。
#include "DxLib.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { int i ; // DXライブラリ初期化処理 if( DxLib_Init() == -1 ) return -1 ; // 一番左上に絵を表示、20分の1秒待つ、を13回繰り返す for( i = 0 ; i < 13 ; i ++ ) { // 画面に描かれているものを一回全部消す ClearDrawScreen() ; // 絵を表示 LoadGraphScreen( i * 10 , 100 , "test1.bmp" , FALSE ) ; // 20分の1秒待つ WaitTimer( 50 ) ; } // キーの入力待ち WaitKey() ; // DXライブラリ使用の終了処理 DxLib_End() ; // ソフトの終了 return 0 ; }
<実行例>

 さて、毎回画面に描かれたものを消すようにしましたがどうでしょう?
 実際に実行してみると分かりますが、ちかちかしてしまいます。ちょっと考えれば当然のことで
『消す→表示→消す→表示』を繰り返せば当然画面には『消す』の状態と『表示』が入れ替わり
立ち代り切り替わるわけで、結果、表示がちかちかしてしまうのです。

 困りました。どうにかして『表示』の状態だけが続くようにしなければなりません。

 実はビデオゲームが作り始められたばかりの頃の人もこのことで悩みました。

 そしてこれに対処する方法が編み出されました、このDXライブラリはその中のパソコン界では
一般的な『ダブルバッファリング』という手法を使ってこれを回避しています。
 次は少し横道にそれてこの『ダブルバッファリング』について解説したいと思います。


戻る