游戏:谁负责展示?

时间:2010-02-03 18:15:21

标签: model-view-controller coding-style

实体应该知道如何画自己吗?我已经使用过这种方法:它很简单而且很有效,但在学习了MVC模式后,我对此感到不安。当所有显示逻辑都隐藏在模型中时,很难改变艺术风格。

可以引入一个视图类,它将该级别作为参数并绘制它,但这意味着它必须识别实体类型并引入“切换” - 语句,我学到的也很糟糕。

人们应该在哪里放置绘图代码,以可扩展的方式,易于更换,清洁和干燥?

4 个答案:

答案 0 :(得分:7)

随着各种工作室和团队开始使用新引擎,这个问题在游戏开发中仍然经常出现。

简短的回答是,这取决于您的游戏实体的复杂程度。对于简单的实体,它并不重要。

当你进入更复杂的实体时,你必须重新考虑你的方法。一般来说,你会想要抵制让uber循环遍历每个实体并调用一些更新/渲染/任何函数的冲动。除非每个更新,渲染或任何层次结构完全相同,否则它根本不会扩展。对于像Geometry Wars这样的游戏来说这很好,但对于比这更复杂的东西都没有。

您想要做的是给出最通用的实体集合提取特定于使用情况的遍历。例如,如果要渲染场景,则应该有一种方法可以从实体集合中提取所有可渲染实体,然后以某种任意的可处理顺序渲染所有可渲染实体。物理,碰撞,AI等同样如此。

一些有用的链接:

http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/ http://research.scee.net/files/presentations/gcapaustralia09/Pitfalls_of_Object_Oriented_Programming_GCAP_09.pdf

我强烈推荐两者;第一部分涉及用于构建游戏实体的设计原理,即渲染组件,物理组件,AI组件。第二部分涉及各种游戏实体方法的性能特征。

答案 1 :(得分:5)

在您的实体中使用抽象的Draw()样式方法并没有什么本质上的错误,这样可以让他们决定如何绘制它们,特别是对于可能不会显着扩展的小型游戏。我已经在很多小项目中使用过这种方法,效果很好。

您可以对该策略进行改进,即将您的游戏资源用作实际绘图操作的代理。例如,敌方实体可以通过其拥有的代表网格的资源对象推迟所有渲染;同样适用于质地/皮肤和效果。

我最近转而使用我的实体作为'哑'容器来定义他们的行为。播放器实体可能包含IMoveable,IControllable,IRenderable以及更多接口,这些接口仅根据其包含的数据将特定操作应用于该实体。实体对此知之甚少,并且遍历场景图以进行剔除/渲染时会执行所有执行。

答案 2 :(得分:3)

MVC不一定非常适合游戏。 MVC是为传统的GUI设计的,它通常基于离散事件不经常更新,而游戏更像是模拟,其中不断更新并且呈现需要立即反映。

尽管如此,你没有理由不再努力将状态与表现分开。实体不需要知道如何绘制自己 - 这意味着他们知道渲染操作,这是不必要的 - 但应该可以问他们如何看待这个时间点,然后使用这些信息来渲染场景。例如。 2D实体应该能够返回其当前的动画帧。或者3D实体应该能够返回其3d网格,位置和方向。这里不需要switch语句,只要您具有可以返回到渲染器的通用表示。具有完全不同的渲染算法的实体可能必须在此时返回相当不同的对象。

答案 3 :(得分:3)

通常我使用继承解决此问题。

例如,在我正在使用的项目中,我正在使用测试驱动开发来编写游戏逻辑,并对渲染进行手动测试。下面C#中的这个例子显示了粗略的想法。

class GameObjecet {
    // Logic, nicely unit tested.
}

class DrawableGameObject : GameObject {
    // Drawing logic - manual testing
}

这通常是我发现的最佳解决方案。这允许对代码进行测试,同时不会使用诸如绘图和模型加载等表示代码来混淆游戏逻辑......