现在的位置: 首页 > 综合 > 正文

2d游戏引擎(二)——向引擎添加位图类

2013年07月01日 ⁄ 综合 ⁄ 共 10374字 ⁄ 字号 评论关闭

 

 位图(Bitmap)类背后的思路是,提供一种从文件或者资源加载位图并将位图绘制到一个设备环境的方法。通过将这些功能结合到一个类中,我们就能够在游戏中创建极易使用的Bitmap对象,并且可以隐藏处理位图的各种繁杂工作。Bitmap类有以下需求:

1.从文件中加载位图

2.从资源中加载位图

3.创建纯色的空白位图

4.将位图绘制到设备环境

5.获得位图的宽度和高度

 

代码清单:

//-----------------------------------------------------------------
// Bitmap Object
// C++ Header - Bitmap.h
//-----------------------------------------------------------------

#pragma once

//-----------------------------------------------------------------
// Include Files
//-----------------------------------------------------------------
#include 

//-----------------------------------------------------------------
// Bitmap Class
//-----------------------------------------------------------------
class Bitmap
{
protected:
  // Member Variables
  HBITMAP m_hBitmap;
  int     m_iWidth, m_iHeight;

  // Helper Methods
  void Free();

public:
  // Constructor(s)/Destructor
  Bitmap();
  Bitmap(HDC hDC, LPTSTR szFileName);
  Bitmap(HDC hDC, UINT uiResID, HINSTANCE hInstance);
  Bitmap(HDC hDC, int iWidth, int iHeight, COLORREF crColor = RGB(0, 0, 0));
  virtual ~Bitmap();

  // General Methods
  BOOL Create(HDC hDC, LPTSTR szFileName);
  BOOL Create(HDC hDC, UINT uiResID, HINSTANCE hInstance);
  BOOL Create(HDC hDC, int iWidth, int iHeight, COLORREF crColor);
  void Draw(HDC hDC, int x, int y);
  int  GetWidth() { return m_iWidth; };
  int  GetHeight() { return m_iHeight; };
};

 

//-----------------------------------------------------------------
// Bitmap Object
// C++ Source - Bitmap.cpp
//-----------------------------------------------------------------

//-----------------------------------------------------------------
// Include Files
//-----------------------------------------------------------------
#include "Bitmap.h"

//-----------------------------------------------------------------
// Bitmap Constructor(s)/Destructor
//-----------------------------------------------------------------
Bitmap::Bitmap()
  : m_hBitmap(NULL), m_iWidth(0), m_iHeight(0)
{
}

// Create a bitmap from a file
Bitmap::Bitmap(HDC hDC, LPTSTR szFileName)
  : m_hBitmap(NULL), m_iWidth(0), m_iHeight(0)
{
  Create(hDC, szFileName);
}

// Create a bitmap from a resource
Bitmap::Bitmap(HDC hDC, UINT uiResID, HINSTANCE hInstance)
  : m_hBitmap(NULL), m_iWidth(0), m_iHeight(0)
{
  Create(hDC, uiResID, hInstance);
}

// Create a blank bitmap from scratch
Bitmap::Bitmap(HDC hDC, int iWidth, int iHeight, COLORREF crColor)
  : m_hBitmap(NULL), m_iWidth(0), m_iHeight(0)
{
  Create(hDC, iWidth, iHeight, crColor);
}

Bitmap::~Bitmap()
{
  Free();
}

//-----------------------------------------------------------------
// Bitmap Helper Methods
//-----------------------------------------------------------------
void Bitmap::Free()
{
  // Delete the bitmap graphics object
  if (m_hBitmap != NULL)
  {
    DeleteObject(m_hBitmap);
    m_hBitmap = NULL;
  }
}

//-----------------------------------------------------------------
// Bitmap General Methods
//-----------------------------------------------------------------
BOOL Bitmap::Create(HDC hDC, LPTSTR szFileName)
{
  // Free any previous bitmap info
  Free();

  // Open the bitmap file
  HANDLE hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  if (hFile == INVALID_HANDLE_VALUE)
    return FALSE;

  // Read the bitmap file header
  BITMAPFILEHEADER  bmfHeader;
  DWORD             dwBytesRead;
  BOOL bOK = ReadFile(hFile, &bmfHeader, sizeof(BITMAPFILEHEADER),
    &dwBytesRead, NULL);
  if ((!bOK) || (dwBytesRead != sizeof(BITMAPFILEHEADER)) ||
    (bmfHeader.bfType != 0x4D42))//0x4D42 代表 "BM",为bmp文件的标志
  {
    CloseHandle(hFile);
    return FALSE;
  }

  BITMAPINFO* pBitmapInfo = (new BITMAPINFO);
  if (pBitmapInfo != NULL)
  {
    // Read the bitmap info header
    bOK = ReadFile(hFile, pBitmapInfo, sizeof(BITMAPINFOHEADER),
      &dwBytesRead, NULL);
    if ((!bOK) || (dwBytesRead != sizeof(BITMAPINFOHEADER)))
    {
      CloseHandle(hFile);
      //Free();
      return FALSE;
    }

    // Store the width and height of the bitmap
    m_iWidth = (int)pBitmapInfo->bmiHeader.biWidth;
    m_iHeight = (int)pBitmapInfo->bmiHeader.biHeight;

    // Get a handle to the bitmap and copy the image bits
    PBYTE pBitmapBits;
    m_hBitmap = CreateDIBSection(hDC, pBitmapInfo, DIB_RGB_COLORS,
      (PVOID*)&pBitmapBits, NULL, 0);
    if ((m_hBitmap != NULL) && (pBitmapBits != NULL))
    {
      SetFilePointer(hFile, bmfHeader.bfOffBits, NULL, FILE_BEGIN);//更改文件指针
      bOK = ReadFile(hFile, pBitmapBits, pBitmapInfo->bmiHeader.biSizeImage,
        &dwBytesRead, NULL);
      if (bOK)
        return TRUE;
    }
  }

  // Something went wrong, so cleanup everything
  Free();
  return FALSE;
}

BOOL Bitmap::Create(HDC hDC, UINT uiResID, HINSTANCE hInstance)
{
  // Free any previous DIB info
  Free();

  // Find the bitmap resource
  HRSRC hResInfo = FindResource(hInstance, MAKEINTRESOURCE(uiResID), RT_BITMAP);
  if (hResInfo == NULL)
    return FALSE;

  // Load the bitmap resource
  HGLOBAL hMemBitmap = LoadResource(hInstance, hResInfo);
  if (hMemBitmap == NULL)
    return FALSE;

  // Lock the resource and access the entire bitmap image
  PBYTE pBitmapImage = (BYTE*)LockResource(hMemBitmap);
  if (pBitmapImage == NULL)
  {
    FreeResource(hMemBitmap);
    return FALSE;
  }

  // Store the width and height of the bitmap
  BITMAPINFO* pBitmapInfo = (BITMAPINFO*)pBitmapImage;
  m_iWidth = (int)pBitmapInfo->bmiHeader.biWidth;
  m_iHeight = (int)pBitmapInfo->bmiHeader.biHeight;

  // Get a handle to the bitmap and copy the image bits
  PBYTE pBitmapBits;
  m_hBitmap = CreateDIBSection(hDC, pBitmapInfo, DIB_RGB_COLORS,
    (PVOID*)&pBitmapBits, NULL, 0);
  if ((m_hBitmap != NULL) && (pBitmapBits != NULL))
  {
    const PBYTE pTempBits = pBitmapImage + pBitmapInfo->bmiHeader.biSize +
      pBitmapInfo->bmiHeader.biClrUsed * sizeof(RGBQUAD);
    //从图像数据区开始copy
    CopyMemory(pBitmapBits, pTempBits, pBitmapInfo->bmiHeader.biSizeImage);

    // Unlock and free the bitmap graphics object
    UnlockResource(hMemBitmap);
    FreeResource(hMemBitmap);
    return TRUE;
  }

  // Something went wrong, so cleanup everything
  UnlockResource(hMemBitmap);
  FreeResource(hMemBitmap);
  Free();
  return FALSE;
}

BOOL Bitmap::Create(HDC hDC, int iWidth, int iHeight, COLORREF crColor)
{
  // Create a blank bitmap
  m_hBitmap = CreateCompatibleBitmap(hDC, iWidth, iHeight);
  if (m_hBitmap == NULL)
    return FALSE;

  // Set the width and height
  m_iWidth = iWidth;
  m_iHeight = iHeight;

  // Create a memory device context to draw on the bitmap
  HDC hMemDC = CreateCompatibleDC(hDC);	//为什么要用兼容的hdc?

  // Create a solid brush to fill the bitmap
  HBRUSH hBrush = CreateSolidBrush(crColor);

  // Select the bitmap into the device context
  HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, m_hBitmap);

  // Fill the bitmap with a solid color
  RECT rcBitmap = { 0, 0, m_iWidth, m_iHeight };
  FillRect(hMemDC, &rcBitmap, hBrush);	

  // Cleanup
  SelectObject(hMemDC, hOldBitmap);
  DeleteDC(hMemDC);
  DeleteObject(hBrush);

  return TRUE;
}

void Bitmap::Draw(HDC hDC, int x, int y)
{
  if (m_hBitmap != NULL)
  {
    // Create a memory device context for the bitmap
    HDC hMemDC = CreateCompatibleDC(hDC);

    // Select the bitmap into the device context
    HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, m_hBitmap);

    // Draw the bitmap to the destination device context
    BitBlt(hDC, x, y, GetWidth(), GetHeight(), hMemDC, 0, 0, SRCCOPY);

    // Restore and delete the memory device context
    SelectObject(hMemDC, hOldBitmap);
    DeleteDC(hMemDC);
  }
}

 

以下给出一个程序实例,应用Bitmap类。程序的效果是在窗口中定时循环显示一组幻灯片。

//-----------------------------------------------------------------
// Slideshow Application
// C++ Header - Slideshow.h
//-----------------------------------------------------------------

#pragma once

//-----------------------------------------------------------------
// Include Files
//-----------------------------------------------------------------
#include 
#include "Resource.h"
#include "GameEngine.h"
#include "Bitmap.h"

//-----------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------
HINSTANCE   g_hInstance;
GameEngine* g_pGame;
const int   g_iNUMSLIDES = 6;	//幻灯片数量
Bitmap*     g_pSlides[g_iNUMSLIDES];
int         g_iCurSlide;

 

//-----------------------------------------------------------------
// Slideshow Application
// C++ Source - Slideshow.cpp
//-----------------------------------------------------------------

//-----------------------------------------------------------------
// Include Files
//-----------------------------------------------------------------
#include "Slideshow.h"

//-----------------------------------------------------------------
// Game Engine Functions
//-----------------------------------------------------------------
BOOL GameInitialize(HINSTANCE hInstance)
{
  // Create the game engine
  g_pGame = new GameEngine(hInstance, TEXT("Slideshow"),
    TEXT("Slideshow"), IDI_SLIDESHOW, IDI_SLIDESHOW_SM);
  if (g_pGame == NULL)
    return FALSE;
  
  // Set the frame rate
  g_pGame->SetFrameRate(1);

  // Store the instance handle
  g_hInstance = hInstance;

  return TRUE;
}

void GameStart(HWND hWindow)
{
  // Create and load the slide bitmaps
  HDC hDC = GetDC(hWindow);
  g_pSlides[0] = new Bitmap(hDC, TEXT("Image1.bmp"));
  g_pSlides[1] = new Bitmap(hDC, TEXT("Image2.bmp"));
  g_pSlides[2] = new Bitmap(hDC, TEXT("Image3.bmp"));
  g_pSlides[3] = new Bitmap(hDC, IDB_IMAGE4, g_hInstance);
  g_pSlides[4] = new Bitmap(hDC, IDB_IMAGE5, g_hInstance);
  g_pSlides[5] = new Bitmap(hDC, 640, 480, RGB(0, 0, 0));

  // Set the first slide
  g_iCurSlide = 0;
}

void GameEnd()
{
  // Cleanup the slide bitmaps
  for (int i = 0; i < g_iNUMSLIDES; i++)
    delete g_pSlides[i];

  // Cleanup the game engine
  delete g_pGame;
}

void GameActivate(HWND hWindow)
{
}

void GameDeactivate(HWND hWindow)
{
}

void GamePaint(HDC hDC)
{
  // Draw the current slide bitmap
  g_pSlides[g_iCurSlide]->Draw(hDC, 0, 0);
}

void GameCycle()
{
  static int iDelay = 0;

  // Establish a 3-second delay before moving to the next slide
  if (++iDelay > 3)
  {
    // Restore the delay counter
    iDelay = 0;

    // Move to the next slide
    if (++g_iCurSlide == g_iNUMSLIDES)
      g_iCurSlide = 0;

    // Force a repaint to draw the next slide
    InvalidateRect(g_pGame->GetWindow(), NULL, FALSE);
  }
}

 

 

//-----------------------------------------------------------------
// Slideshow Resource Identifiers
// C++ Header - Resource.h
//-----------------------------------------------------------------

//-----------------------------------------------------------------
// Icons                    Range : 1000 - 1999
//-----------------------------------------------------------------
#define IDI_SLIDESHOW       1000
#define IDI_SLIDESHOW_SM    1001

//-----------------------------------------------------------------
// Bitmaps                  Range : 2000 - 2999
//-----------------------------------------------------------------
#define IDB_IMAGE1          2000
#define IDB_IMAGE2          2001
#define IDB_IMAGE3          2002
#define IDB_IMAGE4          2003
#define IDB_IMAGE5          2004

 

 

//-----------------------------------------------------------------
// Slideshow Resources
// RC Source - Slideshow.rc
//-----------------------------------------------------------------

//-----------------------------------------------------------------
// Include Files
//-----------------------------------------------------------------
#include "Resource.h"

//-----------------------------------------------------------------
// Icons
//-----------------------------------------------------------------
IDI_SLIDESHOW      ICON         "Res//Slideshow.ico"
IDI_SLIDESHOW_SM   ICON         "Res//Slideshow_sm.ico"

//-----------------------------------------------------------------
// Bitmaps
//-----------------------------------------------------------------
IDB_IMAGE1         BITMAP       "Res//Image1.bmp"
IDB_IMAGE2         BITMAP       "Res//Image2.bmp"
IDB_IMAGE3         BITMAP       "Res//Image3.bmp"
IDB_IMAGE4         BITMAP       "Res//Image4.bmp"
IDB_IMAGE5         BITMAP       "Res//Image5.bmp"

 

 

 

 

 

抱歉!评论已关闭.