赞
踩
子画面的主要目的是模拟游戏中能够随时间移动的图形对象,它具有以下属性:
Bitmap* m_pBitmap; //位图指针
RECT m_rcPosition; //子画面位置
POINT m_ptVelocity; //速度
int m_iZOrder; //z顺序
RECT m_rcBounds; //边界矩形
BOUNDSACTION m_baBoundsAction; //边界动作
BOOL m_bHidden; //可见/隐藏
基于以上属性,子画面(Sprite)类程序清单如下:
//----------------------------------------------------------------- // Sprite Object // C++ Header - Sprite.h //----------------------------------------------------------------- #pragma once //----------------------------------------------------------------- // Include Files //----------------------------------------------------------------- #include #include "Bitmap.h" //----------------------------------------------------------------- // 自定义数据类型(边界动作) //----------------------------------------------------------------- typedef WORD BOUNDSACTION; const BOUNDSACTION BA_STOP = 0, BA_WRAP = 1, BA_BOUNCE = 2, BA_DIE = 3; //----------------------------------------------------------------- // Sprite Class //----------------------------------------------------------------- class Sprite { protected: // Member Variables Bitmap* m_pBitmap; //位图指针 RECT m_rcPosition; //子画面位置 POINT m_ptVelocity; //速度 int m_iZOrder; //z顺序 RECT m_rcBounds; //边界矩形 BOUNDSACTION m_baBoundsAction; //边界动作 BOOL m_bHidden; //可见/隐藏 public: // Constructor(s)/Destructor Sprite(Bitmap* pBitmap); Sprite(Bitmap* pBitmap, RECT& rcBounds, BOUNDSACTION baBoundsAction = BA_STOP); Sprite(Bitmap* pBitmap, POINT ptPosition, POINT ptVelocity, int iZOrder, RECT& rcBounds, BOUNDSACTION baBoundsAction = BA_STOP); virtual ~Sprite(); // General Methods virtual void Update(); void Draw(HDC hDC); BOOL IsPointInside(int x, int y); // 访问方法 RECT& GetPosition() { return m_rcPosition; }; void SetPosition(int x, int y); void SetPosition(POINT ptPosition); void SetPosition(RECT& rcPosition) { CopyRect(&m_rcPosition, &rcPosition); }; void OffsetPosition(int x, int y); POINT GetVelocity() { return m_ptVelocity; }; void SetVelocity(int x, int y); void SetVelocity(POINT ptVelocity); BOOL GetZOrder() { return m_iZOrder; }; void SetZOrder(int iZOrder) { m_iZOrder = iZOrder; }; void SetBounds(RECT& rcBounds) { CopyRect(&m_rcBounds, &rcBounds); }; void SetBoundsAction(BOUNDSACTION ba) { m_baBoundsAction = ba; }; BOOL IsHidden() { return m_bHidden; }; void SetHidden(BOOL bHidden) { m_bHidden = bHidden; }; int GetWidth() { return m_pBitmap->GetWidth(); }; int GetHeight() { return m_pBitmap->GetHeight(); }; }; //----------------------------------------------------------------- // Sprite Inline General Methods //----------------------------------------------------------------- inline BOOL Sprite::IsPointInside(int x, int y) { POINT ptPoint; ptPoint.x = x; ptPoint.y = y; return PtInRect(&m_rcPosition, ptPoint); } //----------------------------------------------------------------- // Sprite Inline Accessor Methods //----------------------------------------------------------------- inline void Sprite::SetPosition(int x, int y) { OffsetRect(&m_rcPosition, x - m_rcPosition.left, y - m_rcPosition.top); } inline void Sprite::SetPosition(POINT ptPosition) { OffsetRect(&m_rcPosition, ptPosition.x - m_rcPosition.left, ptPosition.y - m_rcPosition.top); } inline void Sprite::OffsetPosition(int x, int y) { OffsetRect(&m_rcPosition, x, y); } inline void Sprite::SetVelocity(int x, int y) { m_ptVelocity.x = x; m_ptVelocity.y = y; } inline void Sprite::SetVelocity(POINT ptVelocity) { m_ptVelocity.x = ptVelocity.x; m_ptVelocity.y = ptVelocity.y; }
//----------------------------------------------------------------- // Sprite Object // C++ Source - Sprite.cpp //----------------------------------------------------------------- //----------------------------------------------------------------- // Include Files //----------------------------------------------------------------- #include "Sprite.h" //----------------------------------------------------------------- // Sprite Constructor(s)/Destructor //----------------------------------------------------------------- Sprite::Sprite(Bitmap* pBitmap) { //初始化成员变量 m_pBitmap = pBitmap; SetRect(&m_rcPosition, 0, 0, pBitmap->GetWidth(), pBitmap->GetHeight()); m_ptVelocity.x = m_ptVelocity.y = 0; m_iZOrder = 0; SetRect(&m_rcBounds, 0, 0, 640, 480); m_baBoundsAction = BA_STOP; m_bHidden = FALSE; } Sprite::Sprite(Bitmap* pBitmap, RECT& rcBounds, BOUNDSACTION baBoundsAction) { // 计算一个随机位置 int iXPos = rand() % (rcBounds.right - rcBounds.left); int iYPos = rand() % (rcBounds.bottom - rcBounds.top); // 初始化成员变量 m_pBitmap = pBitmap; SetRect(&m_rcPosition, iXPos, iYPos, iXPos + pBitmap->GetWidth(), iYPos + pBitmap->GetHeight()); m_ptVelocity.x = m_ptVelocity.y = 0; m_iZOrder = 0; CopyRect(&m_rcBounds, &rcBounds); m_baBoundsAction = baBoundsAction; m_bHidden = FALSE; } Sprite::Sprite(Bitmap* pBitmap, POINT ptPosition, POINT ptVelocity, int iZOrder, RECT& rcBounds, BOUNDSACTION baBoundsAction) { //初始化成员变量 m_pBitmap = pBitmap; SetRect(&m_rcPosition, ptPosition.x, ptPosition.y, ptPosition.x + pBitmap->GetWidth(), ptPosition.y + pBitmap->GetHeight()); m_ptVelocity = ptVelocity; m_iZOrder = iZOrder; CopyRect(&m_rcBounds, &rcBounds); m_baBoundsAction = baBoundsAction; m_bHidden = FALSE; } Sprite::~Sprite() { } //----------------------------------------------------------------- // Sprite General Methods //----------------------------------------------------------------- void Sprite::Update() { // 更新位置 POINT ptNewPosition, ptSpriteSize, ptBoundsSize; ptNewPosition.x = m_rcPosition.left + m_ptVelocity.x; ptNewPosition.y = m_rcPosition.top + m_ptVelocity.y; ptSpriteSize.x = m_rcPosition.right - m_rcPosition.left; ptSpriteSize.y = m_rcPosition.bottom - m_rcPosition.top; ptBoundsSize.x = m_rcBounds.right - m_rcBounds.left; ptBoundsSize.y = m_rcBounds.bottom - m_rcBounds.top; // 检查边界动作 // 环绕 if (m_baBoundsAction == BA_WRAP) { if ((ptNewPosition.x + ptSpriteSize.x) < m_rcBounds.left) ptNewPosition.x = m_rcBounds.right; else if (ptNewPosition.x > m_rcBounds.right) ptNewPosition.x = m_rcBounds.left - ptSpriteSize.x; if ((ptNewPosition.y + ptSpriteSize.y) < m_rcBounds.top) ptNewPosition.y = m_rcBounds.bottom; else if (ptNewPosition.y > m_rcBounds.bottom) ptNewPosition.y = m_rcBounds.top - ptSpriteSize.y; } // 弹开 else if (m_baBoundsAction == BA_BOUNCE) { BOOL bBounce = FALSE; POINT ptNewVelocity = m_ptVelocity; if (ptNewPosition.x < m_rcBounds.left) { bBounce = TRUE; ptNewPosition.x = m_rcBounds.left; ptNewVelocity.x = -ptNewVelocity.x; } else if ((ptNewPosition.x + ptSpriteSize.x) > m_rcBounds.right) { bBounce = TRUE; ptNewPosition.x = m_rcBounds.right - ptSpriteSize.x; ptNewVelocity.x = -ptNewVelocity.x; } if (ptNewPosition.y < m_rcBounds.top) { bBounce = TRUE; ptNewPosition.y = m_rcBounds.top; ptNewVelocity.y = -ptNewVelocity.y; } else if ((ptNewPosition.y + ptSpriteSize.y) > m_rcBounds.bottom) { bBounce = TRUE; ptNewPosition.y = m_rcBounds.bottom - ptSpriteSize.y; ptNewVelocity.y = -ptNewVelocity.y; } if (bBounce) SetVelocity(ptNewVelocity); } // 停止(默认) else { if (ptNewPosition.x < m_rcBounds.left || ptNewPosition.x > (m_rcBounds.right - ptSpriteSize.x)) { ptNewPosition.x = max(m_rcBounds.left, min(ptNewPosition.x, m_rcBounds.right - ptSpriteSize.x)); SetVelocity(0, 0); } if (ptNewPosition.y < m_rcBounds.top || ptNewPosition.y > (m_rcBounds.bottom - ptSpriteSize.y)) { ptNewPosition.y = max(m_rcBounds.top, min(ptNewPosition.y, m_rcBounds.bottom - ptSpriteSize.y)); SetVelocity(0, 0); } } SetPosition(ptNewPosition); } void Sprite::Draw(HDC hDC) { // 如果没有隐藏,使用子画面 if (m_pBitmap != NULL && !m_bHidden) m_pBitmap->Draw(hDC, m_rcPosition.left, m_rcPosition.top, TRUE); }
当然附上一个相应的实例程序:创建几个行星子画面,并让它们在游戏屏幕上飞来飞去,分别带有一种边界动作。
程序清单:
//----------------------------------------------------------------- // Planets Application // C++ Header - Planets.h //----------------------------------------------------------------- #pragma once //----------------------------------------------------------------- // Include Files //----------------------------------------------------------------- #include #include "Resource.h" #include "GameEngine.h" #include "Bitmap.h" #include "Sprite.h" //----------------------------------------------------------------- // Global Variables //----------------------------------------------------------------- HINSTANCE g_hInstance; GameEngine* g_pGame; Bitmap* g_pGalaxyBitmap; //背景 Bitmap* g_pPlanetBitmap[3]; //行星位图 Sprite* g_pPlanetSprite[3]; //行星子画面 BOOL g_bDragging; //拖动标志 int g_iDragPlanet; //拖动行星号
//----------------------------------------------------------------- // Planets Application // C++ Source - Planets.cpp //----------------------------------------------------------------- //----------------------------------------------------------------- // Include Files //----------------------------------------------------------------- #include "Planets.h" //----------------------------------------------------------------- // Game Engine Functions //----------------------------------------------------------------- BOOL GameInitialize(HINSTANCE hInstance) { // Create the game engine g_pGame = new GameEngine(hInstance, TEXT("Planets"), TEXT("Planets"), IDI_PLANETS, IDI_PLANETS_SM, 600, 400); if (g_pGame == NULL) return FALSE; // Set the frame rate g_pGame->SetFrameRate(30); // Store the instance handle g_hInstance = hInstance; return TRUE; } void GameStart(HWND hWindow) { // Seed the random number generator srand(GetTickCount()); //创建并加载位图 HDC hDC = GetDC(hWindow); g_pGalaxyBitmap = new Bitmap(hDC, IDB_GALAXY, g_hInstance); g_pPlanetBitmap[0] = new Bitmap(hDC, IDB_PLANET1, g_hInstance); g_pPlanetBitmap[1] = new Bitmap(hDC, IDB_PLANET2, g_hInstance); g_pPlanetBitmap[2] = new Bitmap(hDC, IDB_PLANET3, g_hInstance); //创建行星子画面 RECT rcBounds = { 0, 0, 600, 400 }; g_pPlanetSprite[0] = new Sprite(g_pPlanetBitmap[0], rcBounds); g_pPlanetSprite[1] = new Sprite(g_pPlanetBitmap[1], rcBounds, BA_WRAP); g_pPlanetSprite[2] = new Sprite(g_pPlanetBitmap[2], rcBounds, BA_BOUNCE); g_pPlanetSprite[0]->SetPosition(0, 0); g_pPlanetSprite[0]->SetVelocity(1, 1); g_pPlanetSprite[1]->SetVelocity(2, -1); g_pPlanetSprite[2]->SetVelocity(3, -2); //设置初始拖动信息 g_bDragging = FALSE; g_iDragPlanet = -1; } void GameEnd() { // Cleanup the bitmaps delete g_pGalaxyBitmap; for (int i = 0; i < 3; i++) delete g_pPlanetBitmap[i]; // Cleanup the sprites for (i = 0; i < 3; i++) delete g_pPlanetSprite[i]; // Cleanup the game engine delete g_pGame; } void GameActivate(HWND hWindow) { } void GameDeactivate(HWND hWindow) { } void GamePaint(HDC hDC) { // 绘制星系背景 g_pGalaxyBitmap->Draw(hDC, 0, 0); // 绘制行星子画面 for (int i = 0; i < 3; i++) g_pPlanetSprite[i]->Draw(hDC); } void GameCycle() { // 更新行星子画面 for (int i = 0; i < 3; i++) g_pPlanetSprite[i]->Update(); // Force a repaint to redraw the planets InvalidateRect(g_pGame->GetWindow(), NULL, FALSE); } void HandleKeys() { } void MouseButtonDown(int x, int y, BOOL bLeft) { //查看是否使用鼠标左键单击了一颗行星 if (bLeft && !g_bDragging) { for (int i = 0; i < 3; i++) if (g_pPlanetSprite[i]->IsPointInside(x, y)) { // 捕获鼠标 SetCapture(g_pGame->GetWindow()); // Set the drag state and the drag planet g_bDragging = TRUE; g_iDragPlanet = i; //开始模拟鼠标移动 MouseMove(x, y); // 不检查其他行星 break; } } } void MouseButtonUp(int x, int y, BOOL bLeft) { // 释放鼠标 ReleaseCapture(); // 停止拖动 g_bDragging = FALSE; } void MouseMove(int x, int y) { if (g_bDragging) { //将子画面移动到鼠标指针位置 g_pPlanetSprite[g_iDragPlanet]->SetPosition( x - (g_pPlanetBitmap[g_iDragPlanet]->GetWidth() / 2), y - (g_pPlanetBitmap[g_iDragPlanet]->GetHeight() / 2)); // Force a repaint to redraw the planets InvalidateRect(g_pGame->GetWindow(), NULL, FALSE); } } void HandleJoystick(JOYSTATE jsJoystickState) { }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。