如何从Win32 C ++中的spritesheet中提取位图?

时间:2014-10-31 22:27:50

标签: c++ winapi graphics bitmap

我试图根据套装和等级从卡片的spritesheet中加载单个卡片,但我不确定如何通过剪切源图像中的Rectangle坐标来构造新的Bitmap对象。我目前正在使用<windows.h>,并试图找到一种简单的方法来实现这一目标。我正在寻找这样的事情:

HBITMAP* twoOfHearts = CutOutFromImage(sourceImage, new Rectangle(0, 0, 76, 116));

来自:http://i.stack.imgur.com/WZ9Od.gif

1 个答案:

答案 0 :(得分:0)

这是我和其他一周一起玩的功能,或多或少是同一个任务。在我的情况下,我想返回一个可以与FillRect一起使用的HBRUSH。在那种情况下,我们仍然需要创建一个感兴趣区域的位图,然后再从中创建一个画笔。

在您的情况下,只需返回dstBmp即可。 spriteSheet是一个加载了256x256 spritesheet的全局变量。我已将我精灵的大小硬编码为16x16,你需要将其更改为81x117。

这里有一些代码可以抓取所需区域的副本,还有一些代码可以使用这些&#39;邮票&#39;绘制水平地图。也就是说 - 这种方法存在各种问题。速度是一,过度工作是另一个影响第一个。最后,滚动这样绘制的窗口会产生伪影。

// grabs a 16x16px section from the spriteSheet HBITMAP
HBRUSH getSpriteBrush(int col, int row)
{
    HDC memDC, dstDC, curDC;
    HBITMAP oldMemBmp, oldDstBmp, dstBmp;
    curDC = GetDC(HWND_DESKTOP);

    memDC = CreateCompatibleDC(NULL);
    dstDC = CreateCompatibleDC(NULL);

    dstBmp = CreateCompatibleBitmap(curDC, 16, 16);
    int xOfs, yOfs;
    xOfs = 16 * col;
    yOfs = 16 * row;

    oldMemBmp = (HBITMAP)SelectObject(memDC, spriteSheet);
    oldDstBmp = (HBITMAP)SelectObject(dstDC, dstBmp);
    BitBlt(dstDC,0,0,16,16, memDC, xOfs,yOfs, SRCCOPY);

    SelectObject(memDC, oldMemBmp);
    SelectObject(dstDC, oldDstBmp);
    ReleaseDC(HWND_DESKTOP, curDC);
    DeleteDC(memDC);
    DeleteDC(dstDC);

    HBRUSH result;
    result = CreatePatternBrush(dstBmp);
    DeleteObject(dstBmp);
    return result;
}

void drawCompoundSprite(int x, int y, HDC paintDC, char *tileIndexes, int numCols, int numRows)
{
    int mapCol, mapRow;
    HBRUSH curSprite;
    RECT curDstRect;

    for (mapRow=0; mapRow<numRows; mapRow++)
    {
        for (mapCol=0; mapCol<numCols; mapCol++)
        {
            int curSpriteIndex = tileIndexes[mapRow*numCols + mapCol];
            int spriteX, spriteY;

            spriteX = curSpriteIndex % 16;
            spriteY = curSpriteIndex / 16;

            curDstRect.left = x + 16*mapCol;
            curDstRect.top = y + 16 * mapRow;
            curDstRect.right = curDstRect.left + 16;
            curDstRect.bottom = curDstRect.top + 16;
            curSprite = getSpriteBrush(spriteX, spriteY);
            FillRect(paintDC, &curDstRect, curSprite);
            DeleteObject(curSprite);
        }
    }
}

enter image description here

后一个功能已被替换为以下内容:

void drawCompoundSpriteFast(int x, int y, HDC paintDC, unsigned char *tileIndexes, int numCols, int numRows, pMapInternalData mData)
{

    int mapCol, mapRow;
    HBRUSH curSprite;
    RECT curDstRect;
    HDC memDC;
    HBITMAP oldBmp;
    memDC = CreateCompatibleDC(NULL);
    oldBmp = (HBITMAP)SelectObject(memDC, mData->spriteSheet);

    for (mapRow=0; mapRow<numRows; mapRow++)
    {
        for (mapCol=0; mapCol<numCols; mapCol++)
        {
            int curSpriteIndex = tileIndexes[mapRow*numCols + mapCol];
            int spriteX, spriteY;

            spriteX = curSpriteIndex % mData->tileWidth;
            spriteY = curSpriteIndex / mData->tileHeight


// Draw sprite as-is
//            BitBlt(paintDC, x+16*mapCol, y+16*mapRow,
//                   mData->tileWidth, mData->tileHeight,
//                   memDC,
//                   spriteX * 16, spriteY*16,
//                   SRCCOPY);

// Draw sprite with magenta rgb(255,0,255) areas treated as transparent (empty)
            TransparentBlt(
                           paintDC,
                           x+mData->tileWidth*mapCol, y+mData->tileHeight*mapRow,
                           mData->tileWidth, mData->tileHeight,

                           memDC,
                           spriteX * mData->tileWidth, spriteY*mData->tileHeight,
                           mData->tileWidth, mData->tileHeight,
                           RGB(255,0,255)
                           );
        }
    }
    SelectObject(memDC, oldBmp);
    DeleteObject(memDC);
}