サンプルコードのダウンロード
では、まずサンプルコードをダウンロードし、解凍してください。
私はVisual C++6.0でコンパイルしているので、お持ちの方はVisual C++でプロジェクトファイルを開いてください(「effec_02.dsw」をダブルクリックすれば開けます)。
圧縮ファイルに含まれる「effec_02.exe」をダブルクリックし、実行してみてください(何かキーを押すと終了します)。
どうでしょう?画面が切り替わり、うねうね揺れた地球の画像が3パターン表示されると思います。
というわけで今回は、サインカーブを使用して画像を揺らす方法ついて説明したいと思います。
三角関数は怖くない(謎
三角関数というと、なんだか難しく考える人もいるかもしれませんが、今回は別にムツカシー計算をするわけではありません。
右の図を見てください。
これはだいぶ いびつ ではありますが、サインカーブっぽいものです。
ここでまず覚えて欲しいのは、sin関数は「波形」という事と、最大値・最小値が+1・-1という事です。
それから前にも書きましたが、C言語の場合sin関数の引数の単位はラジアンなので、
360度=2π
1度=π/180
となります(今回はあんまり関係ありませんが)。
地球を歪ませる
さて、ここらでサンプルプログラムを見てみましょう。
今回は、画面中に3パターンの歪む地球を表示させています。
また、DirectDrawに関しては、「DirectDraw基礎 第10回」のサンプルコードを使用しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | //----------[ メイン関数 ]---------------------------------------------------------------------- int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow){ 略 //パレット設定 LoadPalette( "earth.bmp" ); //ビットマップを作業用サーフェイスへ読み込む LoadBitmap(lpWork, "earth.bmp" ,60,15,200,210); int count=0,i; float width=0.f,width_max=50,width_add=0.15f; DWORD tim; while (1){ tim=timeGetTime(); //疑似タイマー処理 ClearScreen(lpBack); //バックバッファクリア count++; //カウンタ //ゆれの大きさを時間によって変化させる(各パターン共通) if (width_add>0){ if ((width+=width_add)>width_max) width_add=-width_add; } else { if ((width+=width_add)<0){ width=0; width_add=-width_add; } } //ゆらすパターン1 SetClipArea(0,0,320,240); for (i=0;i<240;i++) BltClip(lpBack, int ( sin ((count+i)/10.f)*width), i,320,1,lpWork,0,i,FALSE); //ゆらすパターン2 SetClipArea(320,0,320,240); for (i=0;i<320;i++) BltClip(lpBack,320+i, int ( sin ((count+i)/10.f)*width), 1,240,lpWork,i,0,FALSE); //ゆらすパターン3 SetClipArea(0,240,320,240); for (i=0;i<240;i++) BltClip(lpBack, ((i%2)?-1:1)* int ( sin ((count+i)/10.f)*width), 240+i,320,1,lpWork,0,i,FALSE); Flip(); //フリッピング do { //メッセージループ while (PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)){ if (!GetMessage(&msg,NULL,0,0)) Quit(); TranslateMessage(&msg); DispatchMessage(&msg); } } while (timeGetTime()<tim+16); //1000/60=16.666(秒間60回更新予定) } return (FALSE); } |
順番に説明していきましょうか。
まずパレットを読み込み、地球の画像をlpWorkサーフェイスへ読み込んでおきます。
1 2 3 4 5 | //パレット設定 LoadPalette( "earth.bmp" ); //ビットマップを作業用サーフェイスへ読み込む LoadBitmap(lpWork, "earth.bmp" ,60,15,200,210); |
ここで、画像は320×240内の中央へ来るように、読み込んだ画像の転送先をずらしています(60,15)。
(解りやすくなると思ったので(^^;))
そんでもって今日の本題の部分
1 2 3 4 | //ゆらすパターン1 SetClipArea(0,0,320,240); for (i=0;i<240;i++) BltClip(lpBack, int ( sin ((count+i)/10.f)*width),i,320,1,lpWork,0,i,FALSE); |
1つ前の段落でサインカーブについて触れましたが、ここではサインカーブの図を90度右へ回転させたような感じで見ると直ぐに解ると思います(下図参照)。
ここでは画像を、ズバシュァァァ!!と薄く横に切り刻みまくり、それらを横にずらしながら置いていく感じです(謎)。
毎回countをインクリメントする事で、使用する波形の「開始位置」をずらす事が出来ます。
これにより、「動く」うねりを実現出来ます。また、・・・)/10.fと適当に割っていますが、大きな数字で割ると、波の間隔が広くなります。
まぁ、いろいろ変数をいじってみて、「どこを変えるとどうなる」というのを試してみてください(^^;説明するより、そうした方が早いです。
あと、パターン2・パターン3がありますが、これはもう説明するまでもありませんね。