画面からはみ出した画像を表示する・1

BltFast関数もBlt関数も、画像を画面外に描画するとエラーになり、描画が失敗する。
はみ出した部分だけを切り取って、はみ出してない部分だけを描画させるにはどうすればよいかを考える。

キャラクタの左上座標はゲーム領域内にあるが、左下座標がゲーム領域外にあるため、この描画は失敗する(エラー)。
はみ出た部分を切り取って、このように描画させたい。

1.考え方

BltFast関数は、描画予定の左上の座標(x, y)と、描画する画像の矩形(left, top, right, bottom)を与え、バックバッファに転送する。このとき、バックバッファの領域をはみ出して描画した場合、エラーを返す。
つまり、BltFast関数を実行する前に、領域をはみ出しているかどうかを調べ、はみ出している部分があれば画像の矩形を調整し、はみ出さないような矩形にしてからBltFast関数を実行すればよい。
たとえば上の図は、ゲーム領域が640×480で、100×100の画像を(600, 300)の位置に描画すると仮定する。この場合、描画される画像の左上の座標は(600, 300)だが、右下の座標が(600+100, 300+100)で(700, 400)となり、右に700 - 640 = 60ピクセルはみ出してしまう
そこで、画像の矩形(left, top, right, bottom)のうち、rightを60ピクセル縮めれば、ゲーム領域をはみ出さずに描画できる。

私のサンプルプログラムの場合、画像の描画は「myDraw.cpp」内のmyBltFast関数で行っている。この関数を実行する前に、ゲーム領域をはみ出しているかどうかを調べ、矩形や描画座標を調整してからmyBltFast関数を実行すればよい。
しかしこの方法では、効率が悪いため、指定範囲を与えて、その領域をはみ出した部分を調節してから描画(BltFast)を行う関数を作成したほうがよい。

2.関数を作成する

myBltFast関数を元に改造する。

//-----------------------------------------------------------------------------
// 関数名 : myBltFastClip()
// 機能概要: サーフェース間の画像転送(指定矩形内)
// 引 数 : lpDDSOne:転送先サーフェース	dwX,dwY:転送先座標 
//             lpDDSSrc:転送元サーフェース	lpSrcRect:転送元の矩形
//             lpClipRect:表示範囲     dwTrand:転送フラグ
//-----------------------------------------------------------------------------
HRESULT myBltFastClip(LPDIRECTDRAWSURFACE7 lpDDSOne, int dwX, int dwY,
                      LPDIRECTDRAWSURFACE7 lpDDSSrc, LPRECT lpSrcRect, LPRECT lpClipRect, DWORD dwTrand)
{
    HRESULT        hRet;
    int            width, height;

    // 画像の幅と高さを計算
    width = lpSrcRect->right - lpSrcRect->left;
    height = lpSrcRect->bottom - lpSrcRect->top;

    // 指定範囲を超えた画像を切り取る
    if (dwX < lpClipRect->left)
    {
        lpSrcRect->left += (lpClipRect->left - dwX);
        dwX = lpClipRect->left;
    }
    else if (lpClipRect->right < dwX + width)
    {
        lpSrcRect->right -= ((dwX + width) - lpClipRect->right);
    }
    if (dwY < lpClipRect->top)
    {
        lpSrcRect->top += (lpClipRect->top - dwY);
        dwY = lpClipRect->top;
    }
    else if (lpClipRect->bottom < dwY + height)
    {
        lpSrcRect->bottom -= ((dwY + height) - lpClipRect->bottom);
    }

    // 描画処理
    while (TRUE)
    {
        hRet = lpDDSOne->BltFast((DWORD)dwX, (DWORD)dwY, lpDDSSrc, lpSrcRect, DDBLTFAST_WAIT | dwTrand);
        if (hRet == DD_OK)
            break;
        if (hRet == DDERR_SURFACELOST)
        {
            hRet = RestoreDraw();
            if (hRet != DD_OK)
                break;
        }
        if(hRet != DDERR_WASSTILLDRAWING)
            break;
    }

    return hRet;

}

3.関数の置き場所

私の基本プログラムの場合、myDraw.cppに関数を作成し、プロトタイプ宣言をmyDraw.cppとmyDraw.hの両方に行った。これにより、どのソースファイルからもmyBltFastClip関数を呼び出せる。

4.使い方

myBltFastClip関数の引数は次の通り

LPDIRECTDRAWSURFACE7 lpDDSOne
転送先サーフェイス
int dwX
画像転送先座標のX座標。引数がDWORD型ではなくint型であることに注意!!
(DWORD型はunsigned int型、つまりマイナスの値を扱えないため、画面の上や左から現れる場合の座標を持てない)
int dwY
画像転送先座標のX座標。
LPDIRECTDRAWSURFACE7 lpDDSSrc
転送元サーフェイス
LPRECT lpSrcRect
画像の矩形
LPRECT lpClipRect
画像表示領域。この範囲を超えたかどうかで切り取りの処理を行う。
DWORD dwTrand
BltFast関数のパラメータ(DDBLTFAST_〜)

[ TOP ]