Reputation: 100
I have a BitMap (a little sprite) that i have to rotate at a certain angle. I found this code, and i tried to adapt it for my application, but it doesn't seem to work. The sprite doesn't rotate at all, instead it moves a little bit.
Here's the function code:
void Sprite::Rotate(float radians, const char* szImageFile)
{
// Create a memory DC compatible with the display
HDC sourceDC, destDC;
sourceDC = CreateCompatibleDC( mpBackBuffer->getDC() );
destDC = CreateCompatibleDC( mpBackBuffer->getDC() );
// Get logical coordinates
HBITMAP hBitmap = (HBITMAP)LoadImage(g_hInst, szImageFile, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
BITMAP bm;
::GetObject( hBitmap, sizeof( bm ), &bm );
float cosine = (float)cos(radians);
float sine = (float)sin(radians);
// Compute dimensions of the resulting bitmap
// First get the coordinates of the 3 corners other than origin
int x1 = (int)(bm.bmHeight * sine);
int y1 = (int)(bm.bmHeight * cosine);
int x2 = (int)(bm.bmWidth * cosine + bm.bmHeight * sine);
int y2 = (int)(bm.bmHeight * cosine - bm.bmWidth * sine);
int x3 = (int)(bm.bmWidth * cosine);
int y3 = (int)(-bm.bmWidth * sine);
int minx = min(0,min(x1, min(x2,x3)));
int miny = min(0,min(y1, min(y2,y3)));
int maxx = max(0,max(x1, max(x2,x3)));
int maxy = max(0,max(y1, max(y2,y3)));
int w = maxx - minx;
int h = maxy - miny;
// Create a bitmap to hold the result
HBITMAP hbmResult = ::CreateCompatibleBitmap(mpBackBuffer->getDC(), w, h);
HBITMAP hbmOldSource = (HBITMAP)::SelectObject( sourceDC, hBitmap );
HBITMAP hbmOldDest = (HBITMAP)::SelectObject( destDC, hbmResult );
// Draw the background color before we change mapping mode
HBRUSH hbrBack = CreateSolidBrush( mcTransparentColor );
HBRUSH hbrOld = (HBRUSH)::SelectObject( destDC, hbrBack );
PatBlt( destDC, 0, 0, w, h, PATCOPY);
::DeleteObject( ::SelectObject( destDC, hbrOld ) );
// We will use world transform to rotate the bitmap
SetGraphicsMode(destDC, GM_ADVANCED);
XFORM xform;
xform.eM11 = cosine;
xform.eM12 = -sine;
xform.eM21 = sine;
xform.eM22 = cosine;
xform.eDx = (float)-minx;
xform.eDy = (float)-miny;
SetWorldTransform( destDC, &xform );
// Now do the actual rotating - a pixel at a time
BitBlt(destDC, 0, 0, w, h, sourceDC, 0, 0, SRCCOPY );
// Restore DCs
::SelectObject( sourceDC, hbmOldSource );
::SelectObject( destDC, hbmOldDest );
BITMAP btm;
::GetObject( hbmResult, sizeof( mImageBM ), &mImageBM );
}
I can't figure out why it doesn't rotate the image, but instead it moves it. Also if you know another method to do this, i'm open for suggestions, but keep in mind that i can use only winapi, no additional libraries and i'm a beginner in windows programming.
edit: Here is where i got the code: http://www.codeguru.com/cpp/g-m/bitmap/specialeffects/article.php/c1743/ . I had to change it a bit, but i don't think it was because of that, i only changed the CDCs to HDCs. One important thing i've ommited is that the (0, 0) coord. for the image in that code is considered in the corner, but in my application it is in the center of the sprite. Even if that's a problem, i think it is a problem of calculating the new dimensions of the bitmap, i don't see the connection with the rotation.
Upvotes: 1
Views: 3894
Reputation: 12270
If the bitmap is moving, seems to me that the worldtransform and the blit both worked.
Is the amount that it moves due to the eDx/eDy params of the transform?
Does just hard coding the values from the "rotation" example here make a difference? The sines are passed with the opposite sign. So it maybe just ignored the rotation part of the transform and did the translation only.
Upvotes: 2