C#游戏编程:《控制台小游戏系列》之《五、游戏框架完善》

一、游戏框架完善

    前几章中,游戏框架并没有渲染游戏的能力,只是进行一些逻辑输入的运算,并没有把画面反馈到控制台界面。这一章中,我们将要扩展框架的功能,使它能够对游戏画面进行持续渲染。扩展的功能有:游戏的渲染和控制台的重绘,后者的意思是局部更新,则只更新指定的区域部分,其余区域画面保持不变,减小画面因绘制导致的闪烁。下面是游戏框架类的扩展后的实现:
  ///CGame类实现
[csharp]  view plain copy print ?
  1. using System;  
  2. using System.Threading;  
  3. using System.Runtime.InteropServices;  
  4. using CGraphics;  
  5.   
  6. namespace CEngine  
  7. {  
  8.     ///   
  9.     /// 通用游戏类  
  10.     ///   
  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.         ///   
  24.         /// 绘图  
  25.         ///   
  26.         private CDraw m_draw;  
  27.   
  28.         ///   
  29.         /// 重绘事件委托  
  30.         ///   
  31.         ///   
  32.         ///   
  33.         public delegate void PaintEventHandler(TEventArgs e);  
  34.         ///   
  35.         /// 重绘事件  
  36.         ///   
  37.         private event PaintEventHandler m_paint;  
  38.  
  39.         #endregion  
  40.  
  41.         #region 构造函数  
  42.   
  43.         ///   
  44.         /// 构造函数  
  45.         ///   
  46.         public CGame()  
  47.         {  
  48.             //略...  
  49.             m_draw = new CDraw();  
  50.             //略...  
  51.   
  52.             //添加游戏重绘事件  
  53.             m_paint += new PaintEventHandler(onRedraw);  
  54.         }  
  55.  
  56.         #endregion  
  57.  
  58.         #region 游戏运行函数  
  59.   
  60.         ///   
  61.         /// 游戏初始化  
  62.         ///   
  63.         protected abstract void gameInit();  
  64.         ///   
  65.         /// 游戏输入  
  66.         ///   
  67.         private void gameInput()  
  68.         {  
  69.             //处理鼠标事件  
  70.             this.getMouseDevice().mouseEventsHandler();  
  71.             //处理键盘事件  
  72.             this.getKeyboardDevice().keyboardEventsHandler();  
  73.         }  
  74.         ///   
  75.         /// 游戏重绘,只在显式更新时才发生  
  76.         ///   
  77.         ///   
  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.         ///   
  85.         /// 游戏渲染  
  86.         ///   
  87.         ///   
  88.         protected abstract void gameDraw(CDraw draw);  
  89.         ///   
  90.         /// 游戏逻辑  
  91.         ///   
  92.         protected abstract void gameLoop();  
  93.         ///   
  94.         /// 游戏结束  
  95.         ///   
  96.         protected abstract void gameExit();  
  97.  
  98.         #endregion  
  99.   
  100.         //略...  
  101.   
  102.         ///   
  103.         /// 获取控制台区域  
  104.         ///   
  105.         ///   
  106.         protected CRect getClientRect()  
  107.         {  
  108.             return new CRect(Console.WindowLeft, Console.WindowTop, (Console.WindowWidth >>1) - 1, Console.WindowHeight);  
  109.         }  
  110.   
  111.         ///   
  112.         /// 获取绘图对象  
  113.         ///   
  114.         ///   
  115.         protected CDraw getDraw()  
  116.         {  
  117.             return this.m_draw;  
  118.         }  
  119.   
  120.         ///   
  121.         /// 响应重绘事件  
  122.         ///   
  123.         ///   
  124.         private void onPaint(CPaintEventArgs e)  
  125.         {  
  126.             PaintEventHandler temp = m_paint;  
  127.   
  128.             if (temp != null)  
  129.             {  
  130.                 temp(e);  
  131.             }  
  132.         }  
  133.   
  134.         ///   
  135.         /// 更新操作导致重绘整个工作区  
  136.         ///   
  137.         protected void update()  
  138.         {  
  139.             CPaintEventArgs e = new CPaintEventArgs(getClientRect(), getDraw());  
  140.             this.onPaint(e);  
  141.         }  
  142.   
  143.         ///   
  144.         /// 更新操作导致重绘指定区域  
  145.         ///   
  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.         ///   
  157.         /// 游戏运行  
  158.         ///   
  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类实现

[csharp]  view plain copy print ?
  1. using System;  
  2. using CGraphics;  
  3.   
  4. namespace CEngine  
  5. {  
  6.     ///   
  7.     /// 重绘事件参数  
  8.     ///   
  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. }  

  至此,游戏框架类已基本完成,至于声音模块目前就不实现。接下来的几章我们将会使用这个框架实现几个小游戏,以熟悉这个框架的使用方法,并在必要的情况下进行优化,从而更符合使用需求。


二、结语

   这几章下来,一个微型游戏框架逐渐“堆砌”起来了,可以看出,目前框架还非常简陋,从设计、编码、效率来看都非常一般,各方面还需要大家的意见和指点。尽管如此,我们这个框架也不是一无是处,它还是能糊几个小游戏出来的,究竟能做什么小游戏,请看下回分解。

你可能感兴趣的:(C#游戏编程)