记录错误信息
Debug游戏代码可能是非常复杂的,特别是如果您没有得到任何异常,但某些渲染循环却出错。只设置几个断点并不够,尤其是如果游戏在运行一段时间之后遇到错误,Debug并不是正确的选择。您想知道每一帧都运行了什么,但又不想逐步贯穿500帧去发现它。对于这类问题,您可以仅仅抛出一些文本到控制台,不过这只能在Visual Studio中使用,而且当你下次启动项目时将会丢失所有的控制台内容。
在我做过的所有比较大型的项目中,一个最重要的类就是Log类,它只是给一个简单的文本文件写入消息、警告、错误或者Debug文本。这个类本身很简短,也很简单,但如果你以正确的方式使用它,将会给您的debug调试和测试会话更令人愉快。另外,还有更加高级的日志记录类和框架(logging classes and frameworks)可利用,诸如Log4Net,你可以在http://logging.apache.org/log4net/找到。日志不仅仅只是给文本文件写入几行。来自于应用程序的日志数据常常用来远程获取用户错误,借助一个WebService,你可以激活Windows错误事件,还可以做很多其他事情。这些不是本书能涵盖的,因为这是一个非常复杂的话题。对于本书中的简单游戏,使用Log类应该足够了。
先看一看Log类(在Breakout游戏中能找到一个更复杂的版本):
public class Log { #region Variables private static StreamWriter writer = null; private const string LogFilename = "Log.txt"; #endregion
它使用一个Log.txt文件来存储所有消息,并使用一个静态的StreamWriter对象,以便可以方便地在静态方法中访问。
#region Static constructor to create log file static Log() { // Open file FileStream file = new FileStream( LogFilename, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite); writer = new StreamWriter(file); // Go to end of file writer.BaseStream.Seek(0, SeekOrigin.End); // Enable auto flush (always be up to date when reading!) writer.AutoFlush = true; // Add some info about this session writer.WriteLine("/// Session started at: "+ StringHelper.WriteIsoDateAndTime(DateTime.Now)); } // Log() #endregion
在游戏运行的时候,枚举值FileShare.ReadWrite确保你总是可以从外部读写文件。除此之外,要把writer设置到文件的末尾,AutoFlush属性能够确保写入新数据会被立即存储到日志文件中,最后再添加一点儿文本指示这次会话已经开始。对于时间戳你将使用StringHelper类的一个辅助方法,你立刻就会学到这个类。
最后,这是该类的最重要的一个方法、也是您将一直调用的唯一方法:
#region Write log entry static public void Write(string message) { DateTime ct = DateTime.Now; string s = "[" + ct.Hour.ToString("00") + ":" + ct.Minute.ToString("00") + ":" + ct.Second.ToString("00") + "] " + message; writer.WriteLine(s); #if DEBUG // In debug mode write that message to the console as well! System.Console.WriteLine(s); #endif } // Write(message) #endregion
首先,在消息的前面加上一个简单的时间戳。然后消息被写入Log.txt文件中,最后如果项目在debug模式,也把消息输出到控制台。现在,只是通过添加下列代码行,当你每一次完成来自第二章的Breakout游戏的一个关卡,你就给Log.txt文件添加一个新行:
Log.Write("Level " + level + " completed.");