C#2D游戏中对象的结构

时间:2011-09-22 16:05:22

标签: c#

首先,让我为提出一个看起来有点模糊(或形式不正确)的问题而道歉,但我没有经验可以提出更具体的问题。

我正在构建一个引擎,用于在C#中玩2D冒险游戏(你点击一个对象和事物发生的排序),我正在考虑它的最佳结构。你可以想象,当你与一个物体互动时会发生不同的事情:如果它是一扇门,你希望进入另一个房间,如果它是一个人,你希望开始与他们交谈,等等。我的想法是实现这个行为代表们,像这样:

public abstract class GameObject {
    public delegate void onAction();
    public onAction Click;
}

public class Door : GameObject {
    public Door() {
        Click = new onAction(ChangeRoom);
    }
    private void ChangeRoom() {
        //code to change room here
    }
}

public class Person : GameObject {
    public Person() {
        Click = new onAction(StartTalking);
    }
    private void StartTalking() {
        //code to display dialogue here
    }
}

我发现这个解决方案非常优雅,因为如果我想创建一个特殊对象,其某些行为没有被其类覆盖,我可以简单地这样做:

specialObject.Click += new onAction(SpecialMethod);

但这也是事情变得复杂的地方。我希望我的引擎能够简单地通过加载不同的数据来播放不同的游戏,而无需更改引擎本身,因此在引擎内部的某处硬编码SpecialMethod不是一个选项,它必须是数据的一部分。对于普通对象,它都可以用(反)序列化来完成,但从我读过的内容来看,这对代表来说是个问题。你能建议一种方法吗?

P.S。:由于我仍然处于概念层面并且上面的代码尚未实现,因此您可以自由地提出您认为最好的解决方案,甚至可以完全避免代理。

5 个答案:

答案 0 :(得分:3)

您需要的是脚本

本质上,脚本是外部资源(即外部文件),其中包含描述操作的源代码。

C#有不同的选择。

您可以从.NET语言发出程序集。或者您可以在运行时集成另一种语言(例如python)并在脚本中执行。本质上,脚本在正确的时间加载,解释或编译并执行。如果脚本能够修改应用程序状态(数据结构),则可以使用外部数据定义对象行为(数据驱动开发)。

关于这个问题有很多文献,但我觉得建议GPU Programming Gems 6(第4节)。但是,集成一个优秀的脚本引擎所需的努力非常多。这样我试图找出一个基于XML文件的简单逻辑(here是我的问题,加入另一个question来定义XML内容);遗憾的是,我发现这几乎取决于你需要的灵活性。

答案 1 :(得分:1)

您不需要将SpecialMethod功能硬编码到引擎中,您可以在使用引擎的不同游戏中使用它:

var medievalDoor = new Door();
medievalDoor.Click += OpenDoorNormally;

但在另一场比赛中:

var starTrekDoor = new Door();
starTrekDoor.Click += SlideDoorUpward;

只要您公开Click事件,就不需要对引擎中的任何内容进行硬编码。它可以放入你的游戏中,可能将你的引擎作为DLL参考。

答案 2 :(得分:1)

首先,当您缺乏经验时编写引擎可能比您想象的更难。我建议你在没有引擎和硬编码的情况下为你写第一个游戏,然后从经验中学习并编写引擎......我知道这不是你想要的:D

如果您尚未查看http://www.adventuregamestudio.co.uk/使用编辑器,请考虑下面的对象模型。它会有所帮助。

由于您希望您的游戏是数据驱动的,因此您必须能够动态加载和执行代码。 “它不一定是脚本语言。”当你学习如何构建引擎时,建议添加脚本语言并同时学习它是违背我的本性的。 .NET Framework有一个很棒的反射系统,允许您加载C#代码并在运行时编译它。我必须指出,这是C#中的一种脚本,但缺乏对脚本语言的正确定义。

由于你没有很多经验,我的建议是使用定义你的房间的XML文件,并有一个基本的节点序列(命令),定义你点击什么时应该发生什么。您应该在“引擎”中实现所有命令,但是您可以轻松地创建新的房间,因此类似的游戏。 XML也将是非常可扩展的方法,因为它的层次结构允许您添加条件,循环等,这将扩展引擎的“脚本”功能。

答案 3 :(得分:0)

如果执行某些特殊行为的'决定'留给游戏对象本身,我看不出问题。如果您希望引擎决定,那么您认为,您有不兼容的设计规范,因为您将有效地使引擎采取游戏定义的决定,这正是您不想要的。

在游戏对象中创建一个ISpecialBehaviorProvider字段,并在必要时将其设置为适当的值(通过构造函数,公共属性,你有什么)。

只要用户点击,您的引擎就会始终执行GameObject.Click。但是,如果specialBehaviorProvider为空,请让GameObject.Click执行'in class'代码,否则请调用ISpecialBehaviorProvider.SpecialMethod

这样引擎就无法决定调用哪种方法。

答案 4 :(得分:0)

我要注意的第一件事是因为这些是类,所以多态性在这里非常理想 - 例如使用虚拟Click方法。

对于序列化程序,委托确实很棘手,具体取决于序列化方法。 BinaryFormatter 这样做,但我倾向于不惜一切代价避免使用该序列化程序。

如果有可能,我建议您将自定义子类化为标准实现,并使用多态。如果必须通过数据定义纯粹,那么您实际上将实现脚本引擎。 .NET中提供了很多这样的东西 - IronPython可能很有用,虽然对于游戏来说lua很常见(你应该可以很容易地使用Lua.NET)。然后,您可以只有一个与操作关联的可选脚本,并调用脚本(在数据中定义)。