创建一个 Game Service

创建一个 Game Service

  本文来自 http://jsedlak.org/  翻译:猪猪

此文档是基于 XNA Beta 2的

    创建一个Game Service和创建Game Component很相似,实际上你使用的是同一个模板并且继承的是同一个类。创建game services的目的是给你的游戏一个对象,这个对象可以为你做一些不同的事情。这个对象为你的游戏中的其他的 game components 提供服务。Game类中有很多例子这样的例子;Game类通过Game.Services collection来共享graphics device。这意味着任何拥有一个Game对象的引用的类都可以获得一个IGraphicsDeviceService对象的引用,所以graphics device也就当然能使用了。在这个指南中,我们将创建一个game service,他可以用来将文本数据写道硬盘上的文件里。这个指南不需要你了解接口,但是如果你了解这些基础的话将会很有帮助。

     在Game Studio Express中新建一个工程,我将他命名为"Tutorial2"。当默认的文件加载以后,添加一个新建项,选择 Game Component,并起名为"Logger"。当加载完成以后,你将看到一个默认的Game Component 模板出现在你面前。这是因为game service其实就是一个 "global"(全局)的Game component,他为其他的组件提供服务。我们将需要一个System.IO库的引用,添加他到Using Statements(引用声明) 区域.

using System.IO;

     创建一个game service其实非常简单,可以分为两个部分:(1)一个接口,这个接口描述了这个类对其他对象提供的功能 ; (2)将服务添加到game的代码段。这个接口提供了一组其他的组件有用处的方法,属性和事件。也就是说当你请求了一个这个service的引用后就可以使用这些方法属性事件了。 只将必须要提供给外部的部分暴露出来是非常重要的,一个组件如果提供了太多给外部,那么外部将很容易弄乱你的数据,提供太少给外部遗弃很多不错的功能。考虑我们的工程,我们需要给用户(components)提供打开/关闭(open/close)一个文本文件和向文件中写入字符串的功能。我们还需要提供一个允许component检测是否一个文件已经被打开或者关闭的功能。基于这些很少的信息,我们可以创建下面的接口。注意因为这是一个接口的声明,这些函数没有任何的实际代码,他是作为一个模板来提供服务,这些接口交由其他类来实现。

public interface ILoggerService
{
    void LoadFile(string file);
    void CloseFile();

    void Write(string text);
    void WriteLine(string text);

    bool IsOpen { get; }
}

     现在我们拥有了我们的service interface(服务接口),那么让我们继续吧,下面我们要实现我们的Logger组件的函数和他的性质(property)了。继承一个接口类型和继承一个对象的方法是一样的。下面是类的声明。

public partial class Logger : Microsoft.Xna.Framework.GameComponent, ILoggerService

     在我们开始实现每一个函数之前,我们需要先创建一些我们的service要用到的一些成员。我们需要一个字符串来保存我们当前要打开的文件,一个boolean(布尔)型的变量来标示文件是否打开了,我们还需要创建一个表示file stream(文件流)的变量。 在我们的Logger类中创建这些变量然后继续。

#region Members
protected string m_file = "log.txt";
protected bool m_isOpen = false;
protected StreamWriter m_stream;
#endregion

     现在我们已经准备好实现我们的组件继承的接口的函数了。我们先来实现LoadFile和CloseFile,这两个函数负责加载和关闭StreamWriter对象。注意如果这个stream已经被打开了,LoadFile函数将关闭他,除非用户再次打开的是相同的文件。

public void LoadFile(string file)
{
    if (m_isOpen)
    {
        if (m_file.Equals(file))
        {
            this.WriteLine("Log restarted at " + DateTime.Now.ToString() + ".");
            return;
        }

        this.CloseFile();
    }

    m_file = file;

    m_stream = new StreamWriter(m_file);

    m_isOpen = true;

    this.WriteLine("Log started at " + DateTime.Now.ToString() + ".");
}

public void CloseFile()
{
    if (m_isOpen)
    {
        this.WriteLine("Log ended at " + DateTime.Now.ToString() + ".");

        m_stream.Close();
    }
}

     下面的代码段用于允许component向文件中写入文本;两个函数提供两种不同的写入数据的方法。非常类似于System.Console, StreamWriter.Write 和 .WriteLine 的不同,WriteLine在输出的最后添加一个换行(在某些情况下是回车),这样可以让下次输入的文本字符串输入到文件的新行上。最后一小段是表示stream(流)是否打开的属性的代码。

public void Write(string text)
{
    if (m_isOpen)
        m_stream.Write(text);
}

public void WriteLine(string text)
{
    if (m_isOpen)
        m_stream.WriteLine(text);
}

public bool IsOpen
{
    get
    {
        return m_isOpen;
    }
}

     现在你可能正在思考,我们做的这一切是为了创建一个game component ,这个component实现一个非常简单的接口,完全正确。为了让我们的组件成为一个Game Service,我们需要在适当的时间将他加入到了 Game.Services collection(集)中 ,我们可以在Game 对象被传递进我们的构造函数的时候做这个工作。我们还将添加一个事件处理,他负责在程序退出时关闭文件。

public Logger(Game game)
    : base(game)
{
    game.Services.AddService(typeof(ILoggerService), this);
    game.Exiting += new EventHandler(Game_Exiting);
}

void Game_Exiting(object sender, EventArgs e)
{
    this.CloseFile();
}

     现在你的游戏已经拥有了一个完全的Logging service(日志服务)。照着下面的代码来获得service的引用。千万记住要确保这个服务总是在你使用他们之前被添加,否则你将获得一个null引用,这可是很糟糕的哦。如果你想更加深入的了解这个示例,请在下面下载这个指南的源代码。(译注:作者可能疏忽了也可能是觉得太简单了不用提醒,他忘记告诉大家要在工程的Game类中实例化一个logger对象才能从game的对象中获得这个service。)

ILoggerService log = (ILoggerService)this.Services.GetService(typeof(ILoggerService));
 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值