一、游戏框架完善
前几章中,游戏框架并没有渲染游戏的能力,只是进行一些逻辑输入的运算,并没有把画面反馈到控制台界面。这一章中,我们将要扩展框架的功能,使它能够对游戏画面进行持续渲染。扩展的功能有:游戏的渲染和控制台的重绘,后者的意思是局部更新,则只更新指定的区域部分,其余区域画面保持不变,减小画面因绘制导致的闪烁。下面是游戏框架类的扩展后的实现:
///CGame类实现
- using System;
- using System.Threading;
- using System.Runtime.InteropServices;
- using CGraphics;
- namespace CEngine
- {
- /// <summary>
- /// 通用游戏类
- /// </summary>
- public abstract class CGame : ICGame
- {
- #region Api函数
- [DllImport("User32.dll")]
- private static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
- #endregion
- #region 字段
- //略...
- /// <summary>
- /// 绘图
- /// </summary>
- private CDraw m_draw;
- /// <summary>
- /// 重绘事件委托
- /// </summary>
- /// <typeparam name="TEventArgs"></typeparam>
- /// <param name="e"></param>
- public delegate void PaintEventHandler<TEventArgs>(TEventArgs e);
- /// <summary>
- /// 重绘事件
- /// </summary>
- private event PaintEventHandler<CPaintEventArgs> m_paint;
- #endregion
- #region 构造函数
- /// <summary>
- /// 构造函数
- /// </summary>
- public CGame()
- {
- //略...
- m_draw = new CDraw();
- //略...
- //添加游戏重绘事件
- m_paint += new PaintEventHandler<CPaintEventArgs>(onRedraw);
- }
- #endregion
- #region 游戏运行函数
- /// <summary>
- /// 游戏初始化
- /// </summary>
- protected abstract void gameInit();
- /// <summary>
- /// 游戏输入
- /// </summary>
- private void gameInput()
- {
- //处理鼠标事件
- this.getMouseDevice().mouseEventsHandler();
- //处理键盘事件
- this.getKeyboardDevice().keyboardEventsHandler();
- }
- /// <summary>
- /// 游戏重绘,只在显式更新时才发生
- /// </summary>
- /// <param name="e"></param>
- protected virtual void onRedraw(CPaintEventArgs e)
- {
- //缺省是用背景颜色擦除指定区域
- m_draw.setDrawSymbol(CSymbol.DEFAULT);
- m_draw.fillRect(e.getClientRect(), Console.BackgroundColor);
- }
- /// <summary>
- /// 游戏渲染
- /// </summary>
- /// <param name="draw"></param>
- protected abstract void gameDraw(CDraw draw);
- /// <summary>
- /// 游戏逻辑
- /// </summary>
- protected abstract void gameLoop();
- /// <summary>
- /// 游戏结束
- /// </summary>
- protected abstract void gameExit();
- #endregion
- //略...
- /// <summary>
- /// 获取控制台区域
- /// </summary>
- /// <returns></returns>
- protected CRect getClientRect()
- {
- return new CRect(Console.WindowLeft, Console.WindowTop, (Console.WindowWidth >>1) - 1, Console.WindowHeight);
- }
- /// <summary>
- /// 获取绘图对象
- /// </summary>
- /// <returns></returns>
- protected CDraw getDraw()
- {
- return this.m_draw;
- }
- /// <summary>
- /// 响应重绘事件
- /// </summary>
- /// <param name="e"></param>
- private void onPaint(CPaintEventArgs e)
- {
- PaintEventHandler<CPaintEventArgs> temp = m_paint;
- if (temp != null)
- {
- temp(e);
- }
- }
- /// <summary>
- /// 更新操作导致重绘整个工作区
- /// </summary>
- protected void update()
- {
- CPaintEventArgs e = new CPaintEventArgs(getClientRect(), getDraw());
- this.onPaint(e);
- }
- /// <summary>
- /// 更新操作导致重绘指定区域
- /// </summary>
- protected void update(CRect rect)
- {
- CPaintEventArgs e = new CPaintEventArgs(rect, getDraw());
- this.onPaint(e);
- }
- //略...
- #region 游戏启动接口
- /// <summary>
- /// 游戏运行
- /// </summary>
- public void run()
- {
- //游戏初始化
- this.gameInit();
- Int32 startTime = 0;
- while (!this.isGameOver())
- {
- //启动计时
- startTime = Environment.TickCount;
- //计算fps
- this.setFPS();
- //游戏输入
- this.gameInput();
- //游戏逻辑
- this.gameLoop();
- //游戏渲染
- this.gameDraw(m_draw);
- //保持一定的FPS
- while (Environment.TickCount - startTime < this.m_updateRate)
- {
- this.delay();
- }
- }
- //游戏退出
- this.gameExit();
- //释放游戏资源
- this.close();
- }
- #endregion
- //略...
- }
- }
重绘事件参数类实现为:
///CPaintEventArgs类实现
- using System;
- using CGraphics;
- namespace CEngine
- {
- /// <summary>
- /// 重绘事件参数
- /// </summary>
- public sealed class CPaintEventArgs : EventArgs
- {
- private CRect m_rect;
- private CDraw m_draw;
- public CPaintEventArgs(CRect rect, CDraw draw)
- {
- this.m_rect = rect;
- this.m_draw = draw;
- }
- public CRect getClientRect()
- {
- return this.m_rect;
- }
- public void setClientRect(CRect rect)
- {
- this.m_rect = rect;
- }
- public CDraw getDraw()
- {
- return this.m_draw;
- }
- public void setDraw(CDraw draw)
- {
- this.m_draw = draw;
- }
- }
- }
至此,游戏框架类已基本完成,至于声音模块目前就不实现。接下来的几章我们将会使用这个框架实现几个小游戏,以熟悉这个框架的使用方法,并在必要的情况下进行优化,从而更符合使用需求。
这几章下来,一个微型游戏框架逐渐“堆砌”起来了,可以看出,目前框架还非常简陋,从设计、编码、效率来看都非常一般,各方面还需要大家的意见和指点。尽管如此,我们这个框架也不是一无是处,它还是能糊几个小游戏出来的,究竟能做什么小游戏,请看下回分解。