サンプルコードのダウンロード
では、まずサンプルコードをダウンロードし、解凍してください。
私はVisual C++6.0でコンパイルしているので、お持ちの方はVisual C++でプロジェクトファイルを開いてください(「ddraw_10.dsw」をダブルクリックすれば開けます)。
圧縮ファイルに含まれる「ddraw_10.exe」をダブルクリックし、実行してみてください。
どうでしょう?画面が切り替わり、フルスクリーン化し、SLIME(?)と書かれた画像がタイル状に敷き詰められ、左上へスクロールするのが解ると思います。
というわけで今回は、自分で画像転送時にクリッピングしたいと思います。
プログラム側でクリッピング
今回のサンプルの注目すべき点は「スクロール」では無く、画面の端っこのほうに表示している「完全でない画像」です(謎。
今まで、BltFast関数を使用した自作関数Bltでは、転送先で少しでも画像がはみ出てしまうと、何も表示されなくなってしまいます。
で、画面から少しでもはみ出してしまった場合、はみ出ていない部分を表示させる処理がクリッピングと言われています(たぶん)。
int cx1=0,cy1=0,cx2=640,cy2=480; //自前クリッピング処理に使用する範囲 //----------[ クリッピング付きのデータ転送 ]---------------------------------------------------- void BltClip(LPDIRECTDRAWSURFACE saki,int sx,int sy,int width,int height, LPDIRECTDRAWSURFACE moto,int mx,int my,char trans){ DWORD key[2]={DDBLTFAST_NOCOLORKEY,DDBLTFAST_SRCCOLORKEY}; if(sx<cx1){ mx+=cx1-sx; width-=cx1-sx; sx=cx1; if(width<1) return; } if(sy<cy1){ my+=cy1-sy; height-=cy1-sy; sy=cy1; if(height<1) return; } if(sx>=cx2 || sy>=cy2) return; if(sx+width>cx2) width=cx2-sx; if(sy+height>cy2) height=cy2-sy; RECT rec={mx,my,mx+width,my+height}; saki->BltFast(sx,sy,moto,&rec,key[trans] | DDBLTFAST_WAIT); } //----------[ クリッピングする範囲を変更 ]------------------------------------------------------ void SetClipArea(int x,int y,int width,int height){ cx1=x; cy1=y; cx2=x+width; cy2=y+height; }
この自作関数では、転送前に転送先の座標と縦幅、横幅からはみ出している部分を検出し、うまく表示出来るように値を変更しています。
まぁ、見りゃ解りますね(^^;
ついでなのでクリッピングの範囲を変更出来るようにもしておきました。この自作関数では、どこのサーフェイスでも適応されます。
使用例はこんな感じでしょうかね
//クリッピング範囲が全画面(0,0)~(639,479)の場合 SetClipArea(0,0,640,480); //width,heightは0(ゼロ)も1ドットと考えるため639,479にはならない //転送 BltClip(lpBack,-5,0,32,32,lpWork,0,0,0); Flip();
今回は、プログラム側でクリッピングを行いました。
その理由として、DirectDraw側でクリッピングを行うと、家の環境で試したところ、速度がガタ落ちしたからです。
プログラムで処理した方がよっぽど早いですし、応用も利きます。
ただし、この方法にも欠点はあります。それは拡大縮小を行った時にクリッピング出来ないという点です。
というわけで、次回では一応DirectDrawでのクリッピング方法を説明します(私は使ってませんけど)。