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オブジェクトに描画されると考えると良い*1。Matrix::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度で良い。