VC++でGDI+ そにょ6 〜画像の描画2:中心回転〜

中心回転

ゲームなどのスプライトは中心座標が指定されているのが普通である。では、画像の中心を回転中心とした回転関数を書いてみよう。前回紹介した変形描画メソッドを使う。

DrawImage(Image *srcImage, const Point *dstPoints, INT count);
DrawImage(Image *srcImage, const PointF *dstPoints, INT count);

描画する中心座標を(cx, cy)とする。これを中心に時計回りにangle度回転させる。srcからの切り取りなどは各自実装して頂きたい。

#include math.h
Status DrawRotateImage(Graphics *graphics, Image *srcImage, INT cx, INT cy, REAL angle)
{
    UINT w = srcImage->GetWidth()/2;
    UINT h = srcImage->GetHeight()/2;
    
    REAL c = cos(angle*3.14/180);
    REAL s = sin(angle*3.14/180);

    PointF points[3] = 
    {
        PointF(-c*w+s*h+cx, -s*w-c*h+cy),
        PointF( c*w+s*h+cx,  s*w-c*h+cy),
        PointF(-c*w-s*h+cx, -s*w+c*h+cy),
    };

    return graphics->DrawImage(srcImage, points, 3);
}

ん……? そうだ!逆に考えるんだ!キャンバスを回転させればいい!

Status DrawRotateImage(Graphics *graphics, Image *srcImage, INT cx, INT cy, REAL angle)
{    
    INT w = srcImage->GetWidth();
    INT h = srcImage->GetHeight();    
    
    Matrix rotateMatrix;
    rotateMatrix.RotateAt(angle, PointF((REAL)cx,(REAL)cy));
    
    graphics->SetTransform(&rotateMatrix);
    
    Status status = graphics->DrawImage(srcImage, cx-w/2, cy-h/2);

    graphics->ResetTransform();

    return status;
}

Matrixクラスを用いてGraphicsオブジェクトに回転情報を付加する。先ほどキャンバスを回転させると言ったが、実際に回転しているわけではなく、描画するオブジェクトがGraphics::SetTransformメソッドで指定されたMatrixにより変形されてから、Graphicsオブジェクトに描画されると考えると良い*1Matrix::RotateAtメソッドを用いて(cx, cy)を中心にangle度だけ時計回りに回転するMatrixを作成する。これをGraphics::SetTransformメソッドでGraphicsオブジェクトに関連づける。描画した後、Graphics::ResetTransformメソッドで元に戻しておくのを忘れないように。
なおMatrixの平行移動はMatrix::Translateメソッド、拡大縮小はMatrix::Scaleメソッド、回転はMatrix::Rotateメソッドで行える。

反転と90度単位回転

Image::RotateFlipメソッドを使えば反転や、90度単位の回転が行える。引数についてはRotateFlipTypeを参照。

Image* image = new Image(L"hoge.jpg")
image->RotetaFlip(Rotate180FlipX);
graphics.DrawImage(image, 0, 0);

この例ではX軸について反転させて180度回転させている。

*1:キャンバスを回転させると考えると、-angle度回転させるのでは、と思うだろうが、実際回転が適用されるのは描画するオブジェクトなのでRotateAtに渡すのは+angle度で良い。