2D游戏引擎(十一)—— 向游戏引擎添加滚动背景支持

来源:互联网 发布:php ci base url 编辑:程序博客网 时间:2024/05/17 06:45

BackgroundLayer类代表一个滚动背景中的一个单独图层,它存储了一个特定图层的位图图像以及这个图层的视口,速度和方向。它派生自Bitmap类。ScrollingBackground类负责将图层合并到一个滚动背景中。它派生自Background类。

以下是程序清单:

  1. //-----------------------------------------------------------------
  2. // ScrollingBackground Object
  3. // C++ Header - ScrollingBackground.h
  4. //-----------------------------------------------------------------
  5. #pragma once
  6. //-----------------------------------------------------------------
  7. // Include Files
  8. //-----------------------------------------------------------------
  9. #include <windows.h>
  10. #include "Background.h"
  11. //-----------------------------------------------------------------
  12. // Custom Data Types
  13. //-----------------------------------------------------------------
  14. typedef WORD        SCROLLDIR;
  15. const SCROLLDIR     SD_UP     = 0,
  16.                     SD_RIGHT  = 1,
  17.                     SD_DOWN   = 2,
  18.                     SD_LEFT   = 3;
  19. //-----------------------------------------------------------------
  20. // Background Layer Class
  21. //-----------------------------------------------------------------
  22. class BackgroundLayer : Bitmap
  23. {
  24. protected:
  25.   // Member Variables
  26.   RECT      m_rcViewport;
  27.   int       m_iSpeed;
  28.   SCROLLDIR m_sdDirection;
  29. public:
  30.   // Constructor(s)/Destructor
  31.   BackgroundLayer(HDC hDC, LPTSTR szFileName, int iSpeed,
  32.     SCROLLDIR sdDirection);
  33.   BackgroundLayer(HDC hDC, UINT uiResID, HINSTANCE hInstance, int iSpeed = 0,
  34.     SCROLLDIR sdDirection = SD_LEFT);
  35.   // General Methods
  36.   void  Update();
  37.   virtual void  Draw(HDC hDC, int x, int y, BOOL bTrans = FALSE,
  38.     COLORREF crTransColor = RGB(255, 0, 255));
  39.   void          SetSpeed(int iSpeed)  { m_iSpeed = iSpeed; };
  40.   void          SetDirection(SCROLLDIR sdDirection)
  41.     { m_sdDirection = sdDirection; };
  42.   void          SetViewport(RECT& rcViewport)
  43.     { CopyRect(&m_rcViewport, &rcViewport); };
  44. };
  45. //-----------------------------------------------------------------
  46. // Scrolling Background Class
  47. //-----------------------------------------------------------------
  48. class ScrollingBackground : Background
  49. {
  50. protected:
  51.   // Member Variables
  52.   int               m_iNumLayers;
  53.   BackgroundLayer*  m_pLayers[10];
  54. public:
  55.   // Constructor(s)/Destructor
  56.           ScrollingBackground(int iWidth, int iHeight);
  57.   virtual ~ScrollingBackground();
  58.   // General Methods
  59.   virtual void  Update();
  60.   virtual void  Draw(HDC hDC, BOOL bTrans = FALSE,
  61.     COLORREF crTransColor = RGB(255, 0, 255));
  62.   void          AddLayer(BackgroundLayer* pLayer);
  63. };
  1. //-----------------------------------------------------------------
  2. // ScrollingBackground Object
  3. // C++ Source - ScrollingBackground.cpp
  4. //-----------------------------------------------------------------
  5. //-----------------------------------------------------------------
  6. // Include Files
  7. //-----------------------------------------------------------------
  8. #include "ScrollingBackground.h"
  9. //-----------------------------------------------------------------
  10. // BackgroundLayer Constructor(s)/Destructor
  11. //-----------------------------------------------------------------
  12. // Create a background layer from a bitmap file
  13. BackgroundLayer::BackgroundLayer(HDC hDC, LPTSTR szFileName,
  14.   int iSpeed, SCROLLDIR sdDirection)
  15.   : Bitmap(hDC, szFileName), m_iSpeed(iSpeed), m_sdDirection(sdDirection)
  16. {
  17.   // Set the viewport to the entire layer image by default
  18.   m_rcViewport.left = m_rcViewport.top = 0;
  19.   m_rcViewport.right = m_iWidth;
  20.   m_rcViewport.bottom = m_iHeight;
  21. }
  22. // Create a background layer from a bitmap resource
  23. BackgroundLayer::BackgroundLayer(HDC hDC, UINT uiResID, HINSTANCE hInstance,
  24.   int iSpeed, SCROLLDIR sdDirection)
  25.   : Bitmap(hDC, uiResID, hInstance), m_iSpeed(iSpeed),
  26.   m_sdDirection(sdDirection)
  27. {
  28.   // Set the viewport to the entire layer image by default
  29.   m_rcViewport.left = m_rcViewport.top = 0;
  30.   m_rcViewport.right = m_iWidth;
  31.   m_rcViewport.bottom = m_iHeight;
  32. }
  33. void BackgroundLayer::Draw(HDC hDC, int x, int y, BOOL bTrans,
  34.   COLORREF crTransColor)
  35. {
  36.   // Draw only the part of the layer seen through the viewport
  37.   if (m_rcViewport.top < 0 && m_rcViewport.left < 0)
  38.   {
  39.     // Draw the split viewport wrapping top to bottom AND left to right
  40.     DrawPart(hDC, x, y,
  41.       m_iWidth + m_rcViewport.left, m_iHeight + m_rcViewport.top,
  42.       -m_rcViewport.left, -m_rcViewport.top,
  43.       bTrans, crTransColor);
  44.     DrawPart(hDC, x - m_rcViewport.left, y,
  45.       0, m_iHeight + m_rcViewport.top,
  46.       m_rcViewport.right, -m_rcViewport.top,
  47.       bTrans, crTransColor);
  48.     DrawPart(hDC, x, y - m_rcViewport.top,
  49.       m_iWidth + m_rcViewport.left, 0,
  50.       -m_rcViewport.left, m_rcViewport.bottom,
  51.       bTrans, crTransColor);
  52.     DrawPart(hDC, x - m_rcViewport.left, y - m_rcViewport.top,
  53.       0, 0,
  54.       m_rcViewport.right, m_rcViewport.bottom,
  55.       bTrans, crTransColor);
  56.   }
  57.   else if (m_rcViewport.top < 0 && m_rcViewport.right > m_iWidth)
  58.   {
  59.     // Draw the split viewport wrapping top to bottom AND right to left
  60.     DrawPart(hDC, x, y,
  61.       m_rcViewport.left, m_iHeight + m_rcViewport.top,
  62.       m_iWidth - m_rcViewport.left, -m_rcViewport.top,
  63.       bTrans, crTransColor);
  64.     DrawPart(hDC, x + (m_iWidth - m_rcViewport.left), y,
  65.       0, m_iHeight + m_rcViewport.top,
  66.       m_rcViewport.right - m_iWidth, -m_rcViewport.top,
  67.       bTrans, crTransColor);
  68.     DrawPart(hDC, x, y - m_rcViewport.top,
  69.       m_rcViewport.left, 0,
  70.       m_iWidth - m_rcViewport.left, m_rcViewport.bottom,
  71.       bTrans, crTransColor);
  72.     DrawPart(hDC, x + (m_iWidth - m_rcViewport.left), y - m_rcViewport.top,
  73.       0, 0,
  74.       m_rcViewport.right - m_iWidth, m_rcViewport.bottom,
  75.       bTrans, crTransColor);
  76.   }
  77.   else if (m_rcViewport.bottom > m_iHeight && m_rcViewport.left < 0)
  78.   {
  79.     // Draw the split viewport wrapping bottom to top AND left to right
  80.     DrawPart(hDC, x, y,
  81.       m_iWidth + m_rcViewport.left, m_rcViewport.top,
  82.       -m_rcViewport.left, m_iHeight - m_rcViewport.top,
  83.       bTrans, crTransColor);
  84.     DrawPart(hDC, x - m_rcViewport.left, y,
  85.       0, m_rcViewport.top,
  86.       m_rcViewport.right, m_iHeight - m_rcViewport.top,
  87.       bTrans, crTransColor);
  88.     DrawPart(hDC, x, y + (m_iHeight - m_rcViewport.top),
  89.       m_iWidth + m_rcViewport.left, 0,
  90.       -m_rcViewport.left, m_rcViewport.bottom - m_iHeight,
  91.       bTrans, crTransColor);
  92.     DrawPart(hDC, x - m_rcViewport.left, y + (m_iHeight - m_rcViewport.top),
  93.       0, 0,
  94.       m_rcViewport.right, m_rcViewport.bottom - m_iHeight,
  95.       bTrans, crTransColor);
  96.   }
  97.   else if (m_rcViewport.bottom > m_iHeight && m_rcViewport.right > m_iWidth)
  98.   {
  99.     // Draw the split viewport wrapping bottom to top AND right to left
  100.     DrawPart(hDC, x, y,
  101.       m_rcViewport.left, m_rcViewport.top,
  102.       m_iWidth - m_rcViewport.left, m_iHeight - m_rcViewport.top,
  103.       bTrans, crTransColor);
  104.     DrawPart(hDC, x + (m_iWidth - m_rcViewport.left), y,
  105.       0, m_rcViewport.top,
  106.       m_rcViewport.right - m_iWidth, m_iHeight - m_rcViewport.top,
  107.       bTrans, crTransColor);
  108.     DrawPart(hDC, x, y + (m_iHeight - m_rcViewport.top),
  109.       m_rcViewport.left, 0,
  110.       m_iWidth - m_rcViewport.left, m_rcViewport.bottom - m_iHeight,
  111.       bTrans, crTransColor);
  112.     DrawPart(hDC, x + (m_iWidth - m_rcViewport.left), y + (m_iHeight - m_rcViewport.top),
  113.       0, 0,
  114.       m_rcViewport.right - m_iWidth, m_rcViewport.bottom - m_iHeight,
  115.       bTrans, crTransColor);
  116.   }
  117.   else if (m_rcViewport.top < 0)
  118.   {
  119.     // Draw the split viewport wrapping from top to bottom
  120.     DrawPart(hDC, x, y,
  121.       m_rcViewport.left, m_iHeight + m_rcViewport.top,
  122.       m_rcViewport.right - m_rcViewport.left, -m_rcViewport.top,
  123.       bTrans, crTransColor);
  124.     DrawPart(hDC, x, y - m_rcViewport.top,
  125.       m_rcViewport.left, 0,
  126.       m_rcViewport.right - m_rcViewport.left, m_rcViewport.bottom,
  127.       bTrans, crTransColor);
  128.   }
  129.   else if (m_rcViewport.right > m_iWidth)
  130.   {
  131.     // Draw the split viewport wrapping from right to left
  132.     DrawPart(hDC, x, y,
  133.       m_rcViewport.left, m_rcViewport.top,
  134.       m_iWidth - m_rcViewport.left, m_rcViewport.bottom - m_rcViewport.top,
  135.       bTrans, crTransColor);
  136.     DrawPart(hDC, x + (m_iWidth - m_rcViewport.left), y,
  137.       0, m_rcViewport.top,
  138.       m_rcViewport.right - m_iWidth, m_rcViewport.bottom - m_rcViewport.top,
  139.       bTrans, crTransColor);
  140.   }
  141.   else if (m_rcViewport.bottom > m_iHeight)
  142.   {
  143.     // Draw the split viewport wrapping from bottom to top
  144.     DrawPart(hDC, x, y,
  145.       m_rcViewport.left, m_rcViewport.top,
  146.       m_rcViewport.right - m_rcViewport.left, m_iHeight - m_rcViewport.top,
  147.       bTrans, crTransColor);
  148.     DrawPart(hDC, x, y + (m_iHeight - m_rcViewport.top),
  149.       m_rcViewport.left, 0,
  150.       m_rcViewport.right - m_rcViewport.left, m_rcViewport.bottom - m_iHeight,
  151.       bTrans, crTransColor);
  152.   }
  153.   else if (m_rcViewport.left < 0)
  154.   {
  155.     // Draw the split viewport wrapping from left to right
  156.     DrawPart(hDC, x, y,
  157.       m_iWidth + m_rcViewport.left, m_rcViewport.top,
  158.       -m_rcViewport.left, m_rcViewport.bottom - m_rcViewport.top,
  159.       bTrans, crTransColor);
  160.     DrawPart(hDC, x - m_rcViewport.left, y,
  161.       0, m_rcViewport.top,
  162.       m_rcViewport.right, m_rcViewport.bottom - m_rcViewport.top,
  163.       bTrans, crTransColor);
  164.   }
  165.   else
  166.     // Draw the entire viewport at once
  167.     DrawPart(hDC, x, y,
  168.       m_rcViewport.left, m_rcViewport.top,
  169.       m_rcViewport.right - m_rcViewport.left, m_rcViewport.bottom - m_rcViewport.top,
  170.       bTrans, crTransColor);
  171. }
  172. void BackgroundLayer::Update()
  173. {
  174.   switch (m_sdDirection)
  175.   {
  176.   case SD_UP:
  177.     // Move the layer up (slide the viewport down)
  178.     m_rcViewport.top += m_iSpeed;
  179.     m_rcViewport.bottom += m_iSpeed;
  180.     if (m_rcViewport.top > m_iHeight)
  181.     {
  182.       m_rcViewport.bottom = m_rcViewport.bottom - m_rcViewport.top;
  183.       m_rcViewport.top = 0;
  184.     }
  185.     break;
  186.   case SD_RIGHT:
  187.     // Move the layer right (slide the viewport left)
  188.     m_rcViewport.left -= m_iSpeed;
  189.     m_rcViewport.right -= m_iSpeed;
  190.     if (m_rcViewport.right < 0)
  191.     {
  192.       m_rcViewport.left = m_iWidth - (m_rcViewport.right - m_rcViewport.left);
  193.       m_rcViewport.right = m_iWidth;
  194.     }
  195.     break;
  196.   case SD_DOWN:
  197.     // Move the layer down (slide the viewport up)
  198.     m_rcViewport.top -= m_iSpeed;
  199.     m_rcViewport.bottom -= m_iSpeed;
  200.     if (m_rcViewport.bottom < 0)
  201.     {
  202.       m_rcViewport.top = m_iHeight - (m_rcViewport.bottom - m_rcViewport.top);
  203.       m_rcViewport.bottom = m_iHeight;
  204.     }
  205.     break;
  206.   case SD_LEFT:
  207.     // Move the layer left (slide the viewport right)
  208.     m_rcViewport.left += m_iSpeed;
  209.     m_rcViewport.right += m_iSpeed;
  210.     if (m_rcViewport.left > m_iWidth)
  211.     {
  212.       m_rcViewport.right = (m_rcViewport.right - m_rcViewport.left);
  213.       m_rcViewport.left = 0;
  214.     }
  215.     break;
  216.   }
  217. }
  218. //-----------------------------------------------------------------
  219. // ScrollingBackground Constructor(s)/Destructor
  220. //-----------------------------------------------------------------
  221. ScrollingBackground::ScrollingBackground(int iWidth, int iHeight)
  222.   : Background(iWidth, iHeight, 0), m_iNumLayers(0)
  223. {
  224. }
  225. ScrollingBackground::~ScrollingBackground()
  226. {
  227. }
  228. //-----------------------------------------------------------------
  229. // ScrollingBackground General Methods
  230. //-----------------------------------------------------------------
  231. void ScrollingBackground::Update()
  232. {
  233.   // Update the layers
  234.   for (int i = 0; i < m_iNumLayers; i++)
  235.     m_pLayers[i]->Update();
  236. }
  237. void ScrollingBackground::Draw(HDC hDC, BOOL bTrans,
  238.   COLORREF crTransColor)
  239. {
  240.   // Draw the layers
  241.   for (int i = 0; i < m_iNumLayers; i++)
  242.     m_pLayers[i]->Draw(hDC, 0, 0, bTrans, crTransColor);
  243. }
  244. void ScrollingBackground::AddLayer(BackgroundLayer* pLayer)
  245. {
  246.   // Add the new layer (maximum of 10)
  247.   if (m_iNumLayers < 10)
  248.     m_pLayers[m_iNumLayers++] = pLayer;
  249. }