Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 设计游戏对象_C#_Oop_Xna - Fatal编程技术网

C# 设计游戏对象

C# 设计游戏对象,c#,oop,xna,C#,Oop,Xna,最近,我开始使用微软XNA和C#开发一款小游戏,以供自己娱乐。我的问题是关于设计一个游戏对象和继承它的对象。我将把游戏对象定义为可以在屏幕上渲染的东西。为此,我决定创建一个基类,所有其他需要渲染的对象都将继承该基类,称为GameObject。以下代码为I级代码: class GameObject { private Model model = null; private float scale = 1f; private Vector3 position = Vector

最近,我开始使用微软XNA和C#开发一款小游戏,以供自己娱乐。我的问题是关于设计一个游戏对象和继承它的对象。我将把游戏对象定义为可以在屏幕上渲染的东西。为此,我决定创建一个基类,所有其他需要渲染的对象都将继承该基类,称为GameObject。以下代码为I级代码:

class GameObject
{
    private Model model = null;
    private float scale = 1f;
    private Vector3 position = Vector3.Zero;
    private Vector3 rotation = Vector3.Zero;
    private Vector3 velocity = Vector3.Zero;
    private bool alive = false;
    protected ContentManager content;

    #region Constructors
    public GameObject(ContentManager content, string modelResource)
    {
        this.content = content;
        model = content.Load<Model>(modelResource);
    }
    public GameObject(ContentManager content, string modelResource, bool alive)
        : this(content, modelResource)
    {
        this.alive = alive;
    }
    public GameObject(ContentManager content, string modelResource, bool alive, float scale)
        : this(content, modelResource, alive)
    {
        this.scale = scale;
    }
    public GameObject(ContentManager content, string modelResource, bool alive, float scale, Vector3 position)
        : this(content, modelResource, alive, scale)
    {
        this.position = position;
    }
    public GameObject(ContentManager content, string modelResource, bool alive, float scale, Vector3 position, Vector3 rotation)
        : this(content, modelResource, alive, scale, position)
    {
        this.rotation = rotation;
    }
    public GameObject(ContentManager content, string modelResource, bool alive, float scale, Vector3 position, Vector3 rotation, Vector3 velocity)
        : this(content, modelResource, alive, scale, position, rotation)
    {
        this.velocity = velocity;
    }
    #endregion
}
再一次,我省略了任何额外的特定于飞船的方法,比如发射导弹。你认为这种设计是好的,还是应该改进或彻底改变?看起来子类的构造函数很混乱,但这可能是唯一的方法。我从来没有做过这样的事情,我想知道我是否偏离了正轨



感谢所有留下答案的人。他们都很有帮助。似乎有一个普遍的共识,即改变它来使用MVC模式将是最好的。我将进一步研究如何做到这一点。我还将删除大多数构造函数,并且只有一个构造函数,因为modelResource之后的所有参数都不是创建对象所必需的,它们都可以在以后通过方法调用进行更改。

此设计不会将对象的UI部分与对象的行为部分“模型”和“视图”分开可以这么说。这不一定是件坏事,但如果继续使用此设计,您可能会发现以下重构很困难:

  • 通过更改所有艺术资产来重新剥皮游戏
  • 更改许多不同游戏中对象的行为,例如确定对象是否处于活动状态的规则
  • 更改为其他精灵引擎

但是,如果您对这些折衷方案感到满意,并且这种设计对您来说是合理的,那么我认为它没有什么异常的错误

就我个人而言,我发现你有一点不喜欢的构造器的数量,但这是你的选择,根本没有什么问题:)

关于从一个公共基础派生游戏对象的一般策略,这是一种非常常见的方法。甚至是标准的。我倾向于开始使用更类似于MVC的东西,使用只包含数据的轻量级“模型”游戏对象

我在XNA中看到的其他常见方法包括/您可能需要考虑的事项:

  • 实现IRenderable接口,而不是在基类或派生类中执行任何渲染代码。例如,您可能需要从未渲染过的游戏对象-航路点或类似的东西
  • 你可以使你的基类抽象,你不可能想要实例化一个游戏对象

不过,还是有一些小问题。你的设计很好

>根据调用构造函数的频率,可以考虑使所有额外的参数都是空的,当它们没有值时,只将它们传递给NULL。梅西耶创建对象时,构造器减少了

我第一次在XNA中创建游戏时就是这样做的,但下一次我会更多地采用模型/视图类型的方法。模型对象将是您在更新循环中处理的对象,视图将用于绘制循环


当我想使用我的精灵对象处理3D和2D对象时,我遇到了无法将模型与视图分离的问题。它很快就变得一团糟。

我对你们在向量中旋转的存储方法很感兴趣。这是怎么回事? 如果您存储X、Y、Z轴的角度(所谓的欧拉角度),如果您想要创建3D游戏,您应该重新考虑这个想法,因为您将在第一次渲染邪恶后不久遇到


就我个人而言,我不喜欢有这么多构造函数,因为您可以提供1个构造函数,并将所有不需要的参数设置为null。这样,您的界面就更干净了。

这里谈论从视图中分离模型的人是正确的。用面向游戏开发者的术语来说,GameObject和RenderObject应该有单独的类。回想一下你的主要游戏循环:

// main loop
while (true) {
    ProcessInput();  // handle input events
    UpdateGameWorld();  // update game objects
    RenderFrame();  // each render object draws itself
}

您希望更新游戏世界和渲染当前帧的过程尽可能独立。

我还强烈建议使用合成而不是继承的方法来研究基于组件的设计。该思想的要点是基于对象的底层属性对对象建模,并允许这些属性为您完成所有工作

在您的情况下,游戏对象可能具有诸如能够移动、可渲染或具有某种状态等属性。这些独立的功能(或行为)可以建模为对象,并在GameObject中组合,以构建所需的功能


老实说,对于您正在进行的一个小项目,我会专注于使游戏功能化,而不是担心耦合和抽象之类的细节。

或者,您可以创建一个结构或帮助类来保存所有数据,并在结构中包含许多构造函数,这样一来,你只需要在一个对象中,而不是在从GameObject继承的每个类中,有大量的构造函数,这不仅是一个潜在的问题(特别是必须为每个派生类重新定义构造函数),而且构造函数的参数数量也可能成为一个问题。即使将可选参数设置为null,以后也很难读取和维护代码

如果我写:

new Ship(content, "resource", true, null, null, null, null);
第二个空值做什么

如果参数列表超过四个或五个参数,则使用结构保存参数会使代码更可读(但更详细):

GameObjectParams params(content, "resource");
params.IsAlive = true;
new Ship(params);

有很多方法可以做到这一点。

第一场比赛?开始简单。您的基本GameObject(在您的情况下,更恰当地称为DrawableGameObject[注意XNA中的DrawableGameComponent类])应该只包含属于所有GameObj的信息
GameObjectParams params(content, "resource");
params.IsAlive = true;
new Ship(params);