实体是否有能力自我绘制?

时间:2011-10-13 20:58:31

标签: c# design-patterns

这是一个简单的问题,但它是我永远不会确定的问题。这主要是在游戏开发的背景下。假设你有一个实体,比如船只或角色。应该(我知道这是一个意见问题)这个对象包含一个Draw方法吗? (也许实现一个IDrawable接口)

在查看某些游戏项目中的源代码时,我发现这在很多方面都是如此。有时,有一个单独的类可以接受一个实体基础对象并根据其属性(纹理,位置等)绘制它。其他时候,实体被赋予自己的绘制方法,并且它们能够自我渲染。

我希望这个问题不是太主观。有时我会听到人们说绘画之类的东西应该与物品完全分开,他们不应该知道如何画画或有能力。有些更实用,并且觉得这种设计对象具有这种能力是很好的。

我不太确定自己。我没有发现任何类似的问题,因为它可能有点主观,或者任何一种方法都没问题,但我想听听SO有什么说法,因为这些设计决定每天困扰着我的发展。这些小决策,例如对象A是否应该具有执行功能B的能力,或者是否违反某些设计原则。

我敢肯定有些人会说,如果有必要的话,我可以稍后继续我的直觉和重构,但这就是我一直在做的事情,现在我想听听决定某些对象何时应该保持某些能力的实际理论。 / p>

我想我正在寻找的是用于确定给定对象应具有多少权限的启发式方法。

4 个答案:

答案 0 :(得分:3)

你应该选择最简单的方法。即使事实证明你做出了错误的选择,你也可以亲身体验为什么一种方法比另一种方法更好,并且可以在将来应用这些知识。这是有价值的知识,可以帮助您以后做出决定。我发现,我学习某些优点的最佳方法之一就是做错了几次(不是故意记住你),这样你就可以很好地理解一种方法的缺陷。

我处理它的方式是:一个实体拥有绘制它所需的所有信息。例如构成它的精灵,它们相对于实体中心的位置。如果有的话,实体本身做的很少。它实际上只是一个存储其他系统运行信息的地方。

世界渲染代码处理绘制世界及其中的所有实体。它查看给定的实体并在正确的位置绘制每个精灵,应用任何必要的相机变换或效果或者你有什么。

这就是我的大多数游戏的运作方式。实体也不了解物理学或任何东西。它只是一个数据集合,其他系统运行。它不知道物理学,但它确实有一些Box2D结构挂在它上面Box2D在物理更新阶段操作。与AI或输入和其他一切相同。

答案 1 :(得分:3)

每种方法都有它的优点和缺点。

让对象自行绘制的好处:

对双方来说都更舒服。编写引擎的人只需调用一个函数,使用它的人编写这些IDrawable类就可以对所需的一切进行低级访问。如果你想创建一个系统,每个对象必须定义它将使用哪些着色器和纹理,以及如何应用任何特殊效果。你要么拥有一个非常复杂的系统,要么是非常有限的系统。

让渲染器管理和绘制对象的优势

所有现代3D游戏引擎都是这样做的,这是有充分理由的。如果渲染器可以完全控制绑定哪些纹理,使用哪些模型以及哪些着色器处于活动状态,则可以进行优化。假设您使用相同的着色器渲染了很多项目。渲染器可以设置着色器一次,并在一批中渲染它们!如果每个对象都自行绘制,则无法执行此操作。

<强>结论

对于小型项目,每个对象都可以自行绘制。事实上它更舒服。 如果你真的想要性能并希望从显卡中挤出所有内容,那么你需要一个能够严格控制渲染内容和方式的渲染器,以便进行优化。

答案 2 :(得分:1)

  

我想我正在寻找的是一些用于确定方法的启发式方法   给定对象应具有的权限。

我用责任取代权力,然后答案是一个。对于船的行为和绘图的责任对我来说似乎太过分了。

答案 3 :(得分:1)

这取决于你的意思'画自己'。如果你的意思是它应该包含涉及像素或三角形的低级例程,那么可能不是。

我的建议:

  • 表示对象行为的一个类(移动,AI,无论如何)
  • 表示对象外观的一个类
  • 将对象定义为外观和行为组合的一个类

如果'外观'涉及一些自定义绘图例程,那可能在该类中。总的来说,虽然绘图可能是从底层API中抽象出来的,但是使用策略,访问者或某些IoC模式,对象将由一些渲染管理器绘制。在游戏设计中尤其如此,例如在视频内存中交换纹理和以正确的顺序绘制内容非常重要;某些东西需要能够优化对象级别以上的东西。

为了更具体,对象图形的一部分(对象本身或外观细分)实现IRenderable,方法Draw(IRenderEngine)IRenderEngine给出IRenderable 1}}访问DrawSpriteCreateParticleEffect等方法。通过这种方式优化或测量引擎和算法将变得更加容易,如果您需要交换引擎或以非托管,高性能方式(或移植到另一个平台)重新编写,只需创建{{{ 1}}。

提示:如果你这样做,你可以有许多看起来相同/相似的东西,但通过交换行为或许多看起来不同但行为相同的事情采取不同的行动。您还可以在服务器上执行行为事务,并在客户端上发生外观。

我之前做过类似的事情。每个对象类都有一个包含客户端上使用的属性的基类,但在服务器上它是实例化的该类的派生实例,它包括行为(移动,模拟等)。该类还有一个工厂方法,用于提供其相关的IRenderable(外观)接口。实际上这种方法最终有一个非常有效的多人游戏引擎。

相关问题