番外編・・・といっても


さて、ここまでの情報でとりあえず、DirectDraw アプリケーションが
作れるはずであるが、今回の課題には、これ以外の知識が若干必要になる。

とりあえず、点を打つ・・・・なんてのが、ソレだ。

それ以外にも、文字を書いたり線を引いたりできれば、とても便利だ。

実は DirectDraw サーフェイスに対して、Win32 API を使って
文字を書いたり、図形を書いたりできる。

これは実はとても低速なのだが、試験的にやってみる上ではいっこうに
問題なかろう。

以下実例をしめすにとどめる。

これは、Mission4 の続きになっている。

【Misson4 画面】
図1 Mission4 画面


【OnIdle イベントハンドラの編集】
解説
おなじみの ClassWizard を立ち上げる。
再三くどいが、Control-W が近道だ。

クラス名に、CMission1App を選択

メッセージ欄は、OnIdle を選択する。

「コード編集」をクリックする。

そして先ほどの関数を若干変更する。

図2 イベントハンドラの作成


【OnIdle の改造】

OnIdle 関数は、Windows システムがCPUに空きがある限りにおいて、
呼び出すハンドラである。

ここを改造すれば、ゲームやマルチメディアに必要なリアルタイム処理が可能になる。


ここでは、以下の様に改造しよう。

赤字部分が改造点である。

BOOL CMission1App::OnIdle(LONG lCount)
{

#define pi 3.1415926
static double d1=0,d2=0;
int x, y;
BOOL hRet;
DDSURFACEDESC2 ddsd;
DDBLTFX ddbltfx;

CWinApp::OnIdle(lCount);
if (FALSE==::IsWindowEnabled(m_pMainWnd->GetSafeHwnd()))
return TRUE;

ddbltfx.dwSize = sizeof(DDBLTFX);
ddbltfx.dwFillColor = g_dwEraseColor;

// 画面の消去
hRet = g_pDDSOffScreen->Blt(NULL, NULL, NULL, DDBLT_WAIT |
DDBLT_COLORFILL, &ddbltfx);
if (hRet != DD_OK){
if (hRet == DDERR_SURFACELOST)
RestoreAll();
return TRUE;
}

HDC hdc;
char tmp[64];
static long frame_no=0;
POINT pt;

hRet = g_pDDSOffScreen->GetDC(&hdc);
if (hRet==DD_OK){
// 文字表示
sprintf(tmp,"Frame No:%d",frame_no++);
TextOut(hdc,10,10,tmp,strlen(tmp));
pt.y = 240;
x = (frame_no * 2) % 640;
if (x >320)
x = 640-x;
x += 80;
for(pt.x=x;pt.x < (x+158) ; pt.x+=2){
// ドット撃ち
SetPixel(hdc,pt.x,pt.y,255<<16);
SetPixel(hdc,pt.x,pt.y+2,255<<8);
SetPixel(hdc,pt.x,pt.y+4,255);
}
g_pDDSOffScreen->ReleaseDC(hdc);
}

// 元画像の大きさを取得。
RECT rcSrc, rcDest;
ddsd.dwSize = sizeof(ddsd);
g_pDDSOne->GetSurfaceDesc(&ddsd);
rcSrc.left = 0;
rcSrc.top = 0;
rcSrc.right = ddsd.dwWidth;
rcSrc.bottom = ddsd.dwHeight;

// キャラの行動
d1 += 0.07;
d2 += 0.05;
if (d1 > (pi*2))
d1 -= pi*2;
if (d2 > (pi*2))
d2 -= pi*2;
y = (int)(100*sin(d1));
y += 240;
x = (int)(200*sin(d2));
x += 320;
rcDest.top = y;
rcDest.left = x;
rcDest.right = x + ddsd.dwWidth;
rcDest.bottom = y + ddsd.dwHeight;

// 元画像 (g_pDDSOne) から バックバッファ (g_pDDSOffScreen) への矩形転送
g_pDDSOffScreen->Blt(&rcDest, g_pDDSOne, &rcSrc, DDBLT_WAIT, NULL);

hRet = g_pDDSPrimary->Flip(NULL,DDFLIP_WAIT);
if (hRet == DDERR_SURFACELOST)
RestoreAll();
return TRUE;
}



【実行結果】



以上、文字出力・ドット撃ち 処理。

戻る