当前位置:  开发笔记 > 编程语言 > 正文

设计游戏对象

如何解决《设计游戏对象》经验,为你挑选了3个好方法。

我最近开始使用Microsoft XNA和C#开发一款适合自己娱乐的小游戏.我的问题是关于设计游戏对象和继承游戏对象的对象.我将把游戏对象定义为可以在屏幕上呈现的东西.所以为此,我决定创建一个基类,其中所有其他需要渲染的对象都将继承,称为GameObject.下面的代码是我制作的课程:

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(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
}

我遗漏了额外的方法,例如旋转,移动和绘制对象.现在,如果我想创建另一个对象,比如船,我会创建一个Ship类,它将继承GameObject.示例代码如下:

class Ship : GameObject
{
    private int num_missiles = 20; // the number of missiles this ship can have alive at any given time
    private Missile[] missiles;
    private float max_missile_distance = 3000f; // max distance a missile can be from the ship before it dies

    #region Constructors
    public Ship(ContentManager content, string modelResource)
        : base(content, modelResource)
    {
        InitShip();
    }
    public Ship(ContentManager content, string modelResource , bool alive)
        : base(content, modelResource, alive)
    {
        InitShip();
    }
    public Ship(ContentManager content, string modelResource, bool alive, float scale)
        : base(content, modelResource, alive, scale)
    {
        InitShip();
    }
    public Ship(ContentManager content, string modelResource, bool alive, float scale, Vector3 position)
        : base(content, modelResource, alive, scale, position)
    {
        InitShip();
    }
    public Ship(ContentManager content, string modelResource, bool alive, float scale, Vector3 position, Vector3 rotation)
        : base(content, modelResource, alive, scale, position, rotation)
    {
        InitShip();
    }
    public Ship(ContentManager content, string modelResource, bool alive, float scale, Vector3 position, Vector3 rotation, Vector3 velocity)
        : base(content, modelResource, alive, scale, position, rotation, velocity)
    {
        InitShip();
    }
    #endregion
}

同样,我遗漏了任何额外的船舶特定方法,比如发射导弹.你认为这种设计是好还是应该以某种方式改进或完全改变?看起来子类的构造函数很乱,但也许这是唯一的方法.我从来没有做过这样的事情,我想知道我是否偏离轨道.


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



1> NM...:

就个人而言,我发现大量的构造函数你有一点点输出,但这是你的选择,没有任何根本错误:)

关于从共同基础派生游戏对象的一般策略,这是一种非常常见的做事方式.标准,均匀.我倾向于开始使用更类似于MVC的东西,其中包含仅包含数据的非常轻量级的"模型"游戏对象.

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

实现IRenderable接口,而不是在基类或派生类中执行任何呈现代码.例如,您可能想要从未渲染的游戏对象 - 航点或某些东西.

您可以使您的基类抽象,您不太可能想要实例化GameObject.

再说一点,小点.你的设计很好.



2> Jeff B..:

构造函数的数量不仅是一个潜在的问题(特别是必须为每个派生类重新定义它们) - 但构造函数的参数数量可能会成为一个问题.即使您将可选参数设置为可空,也很难在以后读取和维护代码.

如果我写:

new Ship(content, "resource", true, null, null, null, null);

第二个NULL做什么?

如果参数列表超出四个或五个参数,它会使代码更具可读性(但更详细)以保存参数:

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

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



3> mstrobl..:

既然你在问一个与设计相关的问题,我会尝试给出一些提示,而不是你发布的大量代码,因为其他人已经开始了.

游戏非常适合模型 - 视图 - 控制器模式.你明确地谈论了显示部分,但想一想:你在那里有矢量等,这通常是你建模的一部分.把游戏世界和那里的物体想象成模型.他们有一个位置,他们可能有速度和方向.这是MVC的模型部分.

我注意到你想让船开火.例如,您可能希望机械师在控制器类中进行发射,这需要键盘输入.此控制器类将消息发送到模型部分.一个声音很容易想到你可能想要的是在模型上有一些fireAction()方法.在您的基础模型上,这可能是一个可覆盖(虚拟,抽象)的方法.在船上它可能会给游戏世界添加一个"子弹".

看看我如何写了很多关于模型行为的文章,这里有另一件事给我带来了很多帮助:使用策略模式使类的行为可以交换.该策略模式,如果你认为AI和希望也很大行为在未来somewhen改变.你现在可能不知道,但是在一个月内你可能会想要弹道导弹作为默认导弹,如果你使用了策略模板,你可以在以后轻松改变它.

所以最终你可能想要真正做出类似于显示类的东西.它会有像你这样命名的原语:rotate,translate等.并且您希望从中派生它以添加更多功能或更改功能.但想想看,一旦你拥有的不仅仅是一艘船,一种特殊的船,另一种特殊的船,你将会遇到衍生地狱,你会复制很多代码.再次,使用策略模式.并记得保持简单.Displayble类需要具备什么?

意味着知道它相对于屏幕的位置.它可以,这要归功于它的in-world对象的模型以及类似gameworld的模型!

它必须知道要显示其模型及其尺寸的位图.

它必须知道是否有任何东西应该阻止它绘制,如果它不是由绘图引擎处理(即另一个对象遮挡它).

推荐阅读
手机用户2402851335
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有