■ 新・ゲーム開発講座




■ へっぽこプログラミング入門♪


■第22夜:BMP転送

今回は、サーフェイス間のBITMAPの転送です。転送そのものは BitBlt() で一発で終ってしまいますので超簡単♪(笑)さっそく、さくっと行きましょう。


■書式:#g_copy dst_vram,dx,dy,src_vram,sx,sy,width,hight

サーフェイス src_vram の座標 sx,sy 幅 width 高さ hight のパターンをサーフェイス dst_vram の 座標 dx,dy にコピーする。

dst_vram :バックサーフェイス=BS 背景画面=BG パーツ画面=PT
dx,dy :コピー先座標
src_vram :バックサーフェイス=BS 背景画面=BG パーツ画面=PT
sx,sy :コピー元座標
width,hight:幅、高さ


なんだか解析パラメータが多くて大変そうですが、見かけだけです。解析用の小物関数は TextEngine.cpp 内にあるものをコールするだけですし、ここまで来ると実装そのものもルーチンワークのようになってきますね(^^)

■フラグ

BMPの読み込みは一発完了型の処理なので Mainloop() のフラグは関係ありません。

■コマンド解釈部

もう完全に定型化作業ですが(^^)、以下のように処理関数を登録しておきます(TextEngine.cpp)。さすがにもういいかなぁ、ここを解説するのって(笑)


void Command_call()
//「#」を見つけたところでこの関数を呼ぶと、「#」に
//続くコマンド名を解析してその処理関数を呼びます

{

// 省略

//コマンド名の評価 → 処理関数呼び出し
if( strcmp(com_name,"delay" )==0 ){ Com_delay(); flag=ON;} //遅延
if( strcmp(com_name,"wait" )==0 ){ Com_cursor_blink(); flag=ON;} //カーソルブリンク
if( strcmp(com_name,"w" )==0 ){ Com_cursor_blink(); flag=ON;} //カーソルブリンク
if( strcmp(com_name,"halt" )==0 ){ Com_halt(); flag=ON;} //終了
if( strcmp(com_name,"page" )==0 ){ Com_page(); flag=ON;} //改ページ
if( strcmp(com_name,"g_load" )==0 ){ Com_g_load(); flag=ON;} //BMPのLOAD
if( strcmp(com_name,"g_copy" )==0 ){ Com_g_copy(); flag=ON;} //BMPのCOPY

// 省略


}

■処理関数

もはや、解説する意味はないと思います(ううううむ ^^;)。だってパラメータ解釈して BitBlt() に渡しているだけですもの(爆笑)。…ちなみに、ここから講座を読みはじめた方向けに説明しますと、Kaiseki_TextStr() はスクリプトファイルから文字列を切り出す関数、kaiseki_10() は同じく10進数を切り出す関数で、TextEngine.cpp に記述してあります。パラメータ読みの間にある while( *TEXT==',' || *TEXT==' ' || *TEXT==0x0a )TEXT++; という記述はパラメータを区切る 「,」 やスペース、TABの読み捨てです♪ このパターンを覚えてしまえば、スクリプトからAPIをダイレクトに呼ぶのはカンタンだということが分かりますね♪(スピードの問題はありますけど… ^^)


int Com_g_copy()
{

char dst_vram[256],src_vram[256];
int dx,dy,sx,sy,width,hight;

TEXT++;

//コピー先画面
strcpy( dst_vram, Kaiseki_TextStr() );
while( *TEXT==',' || *TEXT==' ' || *TEXT==0x0a )TEXT++;

//dx
dx = kaiseki_10();
while( *TEXT==',' || *TEXT==' ' || *TEXT==0x0a )TEXT++;

//dy
dy = kaiseki_10();
while( *TEXT==',' || *TEXT==' ' || *TEXT==0x0a )TEXT++;

//コピー元画面
strcpy( src_vram, Kaiseki_TextStr() );
while( *TEXT==',' || *TEXT==' ' || *TEXT==0x0a )TEXT++;

//sx
sx = kaiseki_10();
while( *TEXT==',' || *TEXT==' ' || *TEXT==0x0a )TEXT++;

//sy
sy = kaiseki_10();
while( *TEXT==',' || *TEXT==' ' || *TEXT==0x0a )TEXT++;

//width
width = kaiseki_10();
while( *TEXT==',' || *TEXT==' ' || *TEXT==0x0a )TEXT++;

//hight
hight = kaiseki_10();

//↓とりあえず、そのままパラメータを渡しているだけです。
BitBlt( Get_game_DC(dst_vram),dx,dy,width,hight,Get_game_DC(src_vram),sx,sy,SRCCOPY );

return 0;


}

さて、こんな簡単なコマンドではありますが、ソースとサンプルスクリプトはちゃんと用意してあります。こちらをダウンロードして実行してみると、以下のような画面になると思います。これで、最低限の画面操作はできるようになった訳ですね。



ところで、実行してみて「あれ・・・なんか遅くない?」という感想を持たれた方もいると思います。そうです。現在の仕様ではサンプルスクリプト(default.txt)のようにコマンドをだ〜〜っと並べて記述した場合、その解釈プロセス毎に @1文字表示毎のウェイトAバックサーフェイス→表画面への全面転送 のタイムコストが上乗せされてしまうので遅くなってしまいます。特に現在の仕様では、文字表示ウェイトはスペースやTAB、改行の CR、LF にもすべてかかってきてしまいます。これを回避するいは@とAのプロセスをワープして解釈ルーチンを回せば良いのですが、少々面倒な処理なのでここでは割愛しておきます。拙作「彼女と触手」では既に解決していているのですが、まあ後日の楽しみということにしておきましょう(^^)


※補足
パラメータの並びが #g_copy コマンドと BitBlt() で異なっていますが、これはくににんの趣味的なものなので、気にいらなかったら BitBlt() に合せた順番に直してください。コマンドを使う側としては「幅と高さは転送元の属性だろー!」というだけのことですから(笑)。ちなみにマイクロソフトが「幅、高さ」を転送先の属性にしたのはOS側の発想だと思います。ウィンドウが重なって露出面積が小さくなったとき、隠れた部分は転送しないで速度を稼ごう・・・という思考の延長ではないかとくににんは想像しています。余談ですが、試しにソースをコンパイルして実行中に、別ウィンドウを上に重ねながらFPS値を観察してみてください。露出面積が小さくなるほど驚異的な数値が観察できます(^^;)。画像転送面積が減ると、これだけ Mainloop() がぶんぶん回るとゆーことですね〜(うーむ)。