C#遊戲編程:《控制檯小遊戲系列》之《五、遊戲框架完善》

一、遊戲框架完善

  前幾章中,遊戲框架並沒有渲染遊戲的能力,只是進行一些邏輯輸入的運算,並沒有把畫面反饋到控制檯界面。這一章中,我們將要擴展框架的功能,使它能夠對遊戲畫面進行持續渲染。擴展的功能有:遊戲的渲染和控制檯的重繪,後者的意思是局部更新,則只更新指定的區域部分,其餘區域畫面保持不變,減小畫面因繪製導致的閃爍。下面是遊戲框架類的擴展後的實現:
  ///CGame類實現
  1. using System;  
  2. using System.Threading;  
  3. using System.Runtime.InteropServices;  
  4. using CGraphics;  
  5.   
  6. namespace CEngine  
  7. {  
  8.     /// <summary>  
  9.     /// 通用遊戲類  
  10.     /// </summary>  
  11.     public abstract class CGame : ICGame  
  12.     {  
  13.         #region Api函數  
  14.         [DllImport("User32.dll")]  
  15.         private static extern IntPtr FindWindow(String lpClassName, String lpWindowName);  
  16.  
  17.         #endregion  
  18.  
  19.         #region 字段  
  20.   
  21.         //略...  
  22.   
  23.         /// <summary>  
  24.         /// 繪圖  
  25.         /// </summary>  
  26.         private CDraw m_draw;  
  27.   
  28.         /// <summary>  
  29.         /// 重繪事件委託  
  30.         /// </summary>  
  31.         /// <typeparam name="TEventArgs"></typeparam>  
  32.         /// <param name="e"></param>  
  33.         public delegate void PaintEventHandler<TEventArgs>(TEventArgs e);  
  34.         /// <summary>  
  35.         /// 重繪事件  
  36.         /// </summary>  
  37.         private event PaintEventHandler<CPaintEventArgs> m_paint;  
  38.  
  39.         #endregion  
  40.  
  41.         #region 構造函數  
  42.   
  43.         /// <summary>  
  44.         /// 構造函數  
  45.         /// </summary>  
  46.         public CGame()  
  47.         {  
  48.             //略...  
  49.             m_draw = new CDraw();  
  50.             //略...  
  51.   
  52.             //添加遊戲重繪事件  
  53.             m_paint += new PaintEventHandler<CPaintEventArgs>(onRedraw);  
  54.         }  
  55.  
  56.         #endregion  
  57.  
  58.         #region 遊戲運行函數  
  59.   
  60.         /// <summary>  
  61.         /// 遊戲初始化  
  62.         /// </summary>  
  63.         protected abstract void gameInit();  
  64.         /// <summary>  
  65.         /// 遊戲輸入  
  66.         /// </summary>  
  67.         private void gameInput()  
  68.         {  
  69.             //處理鼠標事件  
  70.             this.getMouseDevice().mouseEventsHandler();  
  71.             //處理鍵盤事件  
  72.             this.getKeyboardDevice().keyboardEventsHandler();  
  73.         }  
  74.         /// <summary>  
  75.         /// 遊戲重繪,只在顯式更新時才發生  
  76.         /// </summary>  
  77.         /// <param name="e"></param>  
  78.         protected virtual void onRedraw(CPaintEventArgs e)  
  79.         {  
  80.             //缺省是用背景顏色擦除指定區域  
  81.             m_draw.setDrawSymbol(CSymbol.DEFAULT);  
  82.             m_draw.fillRect(e.getClientRect(), Console.BackgroundColor);  
  83.         }  
  84.         /// <summary>  
  85.         /// 遊戲渲染  
  86.         /// </summary>  
  87.         /// <param name="draw"></param>  
  88.         protected abstract void gameDraw(CDraw draw);  
  89.         /// <summary>  
  90.         /// 遊戲邏輯  
  91.         /// </summary>  
  92.         protected abstract void gameLoop();  
  93.         /// <summary>  
  94.         /// 遊戲結束  
  95.         /// </summary>  
  96.         protected abstract void gameExit();  
  97.  
  98.         #endregion  
  99.   
  100.         //略...  
  101.   
  102.         /// <summary>  
  103.         /// 獲取控制檯區域  
  104.         /// </summary>  
  105.         /// <returns></returns>  
  106.         protected CRect getClientRect()  
  107.         {  
  108.             return new CRect(Console.WindowLeft, Console.WindowTop, (Console.WindowWidth >>1) - 1, Console.WindowHeight);  
  109.         }  
  110.   
  111.         /// <summary>  
  112.         /// 獲取繪圖對象  
  113.         /// </summary>  
  114.         /// <returns></returns>  
  115.         protected CDraw getDraw()  
  116.         {  
  117.             return this.m_draw;  
  118.         }  
  119.   
  120.         /// <summary>  
  121.         /// 響應重繪事件  
  122.         /// </summary>  
  123.         /// <param name="e"></param>  
  124.         private void onPaint(CPaintEventArgs e)  
  125.         {  
  126.             PaintEventHandler<CPaintEventArgs> temp = m_paint;  
  127.   
  128.             if (temp != null)  
  129.             {  
  130.                 temp(e);  
  131.             }  
  132.         }  
  133.   
  134.         /// <summary>  
  135.         /// 更新操作導致重繪整個工作區  
  136.         /// </summary>  
  137.         protected void update()  
  138.         {  
  139.             CPaintEventArgs e = new CPaintEventArgs(getClientRect(), getDraw());  
  140.             this.onPaint(e);  
  141.         }  
  142.   
  143.         /// <summary>  
  144.         /// 更新操作導致重繪指定區域  
  145.         /// </summary>  
  146.         protected void update(CRect rect)  
  147.         {  
  148.             CPaintEventArgs e = new CPaintEventArgs(rect, getDraw());  
  149.             this.onPaint(e);  
  150.         }  
  151.   
  152.         //略...  
  153.  
  154.         #region 遊戲啓動接口  
  155.   
  156.         /// <summary>  
  157.         /// 遊戲運行  
  158.         /// </summary>  
  159.         public void run()  
  160.         {  
  161.             //遊戲初始化  
  162.             this.gameInit();  
  163.   
  164.             Int32 startTime = 0;  
  165.             while (!this.isGameOver())  
  166.             {  
  167.                 //啓動計時  
  168.                 startTime = Environment.TickCount;  
  169.                 //計算fps  
  170.                 this.setFPS();  
  171.                 //遊戲輸入  
  172.                 this.gameInput();  
  173.                 //遊戲邏輯  
  174.                 this.gameLoop();  
  175.                 //遊戲渲染  
  176.                 this.gameDraw(m_draw);  
  177.   
  178.                 //保持一定的FPS  
  179.                 while (Environment.TickCount - startTime < this.m_updateRate)  
  180.                 {  
  181.                     this.delay();  
  182.                 }  
  183.             }  
  184.   
  185.             //遊戲退出  
  186.             this.gameExit();  
  187.             //釋放遊戲資源  
  188.             this.close();  
  189.         }  
  190.  
  191.         #endregion  
  192.          
  193.         //略...  
  194.     }  
  195. }  

  重繪事件參數類實現爲:

  ///CPaintEventArgs類實現

  1. using System;  
  2. using CGraphics;  
  3.   
  4. namespace CEngine  
  5. {  
  6.     /// <summary>  
  7.     /// 重繪事件參數  
  8.     /// </summary>  
  9.     public sealed class CPaintEventArgs : EventArgs  
  10.     {  
  11.         private CRect m_rect;  
  12.         private CDraw m_draw;  
  13.   
  14.         public CPaintEventArgs(CRect rect, CDraw draw)  
  15.         {  
  16.             this.m_rect = rect;  
  17.             this.m_draw = draw;  
  18.         }  
  19.   
  20.         public CRect getClientRect()  
  21.         {  
  22.             return this.m_rect;  
  23.         }  
  24.   
  25.         public void setClientRect(CRect rect)  
  26.         {  
  27.             this.m_rect = rect;  
  28.         }  
  29.   
  30.         public CDraw getDraw()  
  31.         {  
  32.             return this.m_draw;  
  33.         }  
  34.   
  35.         public void setDraw(CDraw draw)  
  36.         {  
  37.             this.m_draw = draw;  
  38.         }  
  39.     }  
  40. }  

  至此,遊戲框架類已基本完成,至於聲音模塊目前就不實現。接下來的幾章我們將會使用這個框架實現幾個小遊戲,以熟悉這個框架的使用方法,並在必要的情況下進行優化,從而更符合使用需求。


二、結語

  這幾章下來,一個微型遊戲框架逐漸“堆砌”起來了,可以看出,目前框架還非常簡陋,從設計、編碼、效率來看都非常一般,各方面還需要大家的意見和指點。儘管如此,我們這個框架也不是一無是處,它還是能糊幾個小遊戲出來的,究竟能做什麼小遊戲,請看下回分解。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章