有关XNA游戏架构的问题


12

因此,我终于开始玩XNA了,并一直在制作2D游戏(我从iOS上开发它的朋友那里得到了很多美术资产)

许多事情似乎很容易做到,而且开箱即用,但是由于大多数文献(例如,我买的书)对2D的关注都不多,所以我一头雾水。

对于以下问题的任何澄清或指向更多信息,我将不胜感激:

  1. 游戏服务的意义是什么?我了解将对象注册为服务的全部习惯,以便任何其他GameComponent都可以抢占它,但是如何击败这个问题却仅仅是使其成为公共的还是静态的?例如,我的书建议在Game.cs类中注册SpriteBatch对象。我不确定将其简单地设置为公共/静态是多么可取,因为无论如何应该只存在一个Game实例(单个)?

  2. 我对何时应该从GameComponent或RenderableGameComponent继承感到困惑。我正在尝试遵循管理器/控制器的设计,以便所有实体都由一个管理器创建/拥有,其他事物也一样。我目前有每个Manager / Controller都继承自GameComponent,但是如何让Game对象拥有所有Manager并手动调用它们的更新并绘制呢?

  3. 我注意到初始化是 ContentLoad()之前调用的,我发现这很烦人,因为在我的Initialize中我想创建一些实体(即Sprite,Player等),但是我无法为其加载它们由于尚未调用SpriteSheets或Textures,因此尚未进行调用。我可能是初始化不正确,还是人们只是在ContentLoad中进一步分配纹理?

那些似乎是我最大的“ WTF ”,不是很了解

Answers:


11

您的问题的答案很简单:做任何有效的事情。理想情况下,做简单而有效的事情。通常,使用内置体系结构并不简单,因为正如您所发现的那样,您必须跳过篮球,以自己想要的方式构造游戏。

要回答第一个问题,我将带您参考对“为什么使用服务?”这一问题的回答。。简短的答案是,服务是避免在独立游戏中永远不会遇到的耦合(版本,依赖关系,可扩展性)问题的好方法。在大多数情况下,只需要注册一个成员publicstatic如果您急着甚至还可以)并担心更多有趣的问题,就更容易了。

为了回答您的第二个问题,我将向您介绍我对“游戏对象的每个实例都使用DrawableGameComponent的缺点”的回答。以及我对游戏结构的想法。简短的回答是:没有使用任何好处GameComponent了,只需要创建自己的类,并呼吁类似的方法DrawUpdate你自己。如果GameComponent与您想要的架构完全匹配,请务必使用它-但几乎总是不使用它。

仅当您要构建供第三方使用的库时,使用服务和组件才真正变得有趣。XNA本身就是这样做的- 例如,它具有IGraphicsDeviceServiceGamerServicesComponent。它们满足了开发游戏时通常不会遇到的特定去耦要求。

最后,第三个问题的答案非常简单:只需在中创建游戏实体LoadContent。没有什么特别的Initialize

值得指出的是,整个Microsoft.Xna.Framework.Game程序集是可选的。它提供了一个非常有用的起点-但绝不应将其视为做事的“正确方法”。


非常有趣的观看方式。比我的回答要现实得多,脚踏实地。先生,当之无愧+1。
杰西·埃蒙德

我还有一个问题!绘制Texture2D时的原点如何?将原点放置在纹理的底部中间是否常见?我正在尝试制作动画,但我发现原点位于(0,0)会导致宽度和高度不相同的情况导致纹理略微移位
Setheron 2011年

@Setheron:您应该真正创建一个新问题-因为这与原始问题完全无关。我将还原您对此问题所做的编辑。SpriteBatch.Draw相对于纹理左上角的纹理像素坐标指定了原点(如果使用,则为源矩形)。
安德鲁·罗素

1
@Andrew:我最近重构了游戏,使其完全基于服务而非public/ static属性。为什么?可测试性。几乎不可能用属性方法来解决问题,而如果一切都用a初始化并且IServiceProvider可以用您的测试方法填充类所需的任何东西,那将是微不足道的。它还避免了Game在测试中实例化对象本身的需要,因为它很快就会变得混乱。
Matthew Scharley 2011年

顺便说一句,我仍然在Game对象上有很多公共属性。只是碰巧通过接口将它们访问Game.Services,然后将接口传递给所有东西以再次获得所需的东西。
Matthew Scharley 2011年

3

对于第一个问题,我必须承认我真的不知道实际答案。我想这与单例通常是一种不良设计模式的原因相同。我将引您引用此链接的引文:

我们想到的第一个(也是引入服务的原因之一)是在游戏中提供GraphicsDevice引用,最初我们让Game拥有GraphicsDevice并通过诸如Game.GraphicsDevice之类的属性公开它。问题在于,这将GraphicsDevice紧密地绑定到了游戏,不允许其他人“拥有”该设备(例如渲染器),并阻止某人使用将来更新的GraphicsDevice而不发布不会发行新版本的Game的游戏。向后兼容。

对于您的第二个问题,我假设如果您遵循基于组件的方法,则使用像这样的组件会更有用,就像您将拥有一系列Sprite知道如何绘制和更新自身的组件而不是组件一样。知道如何更新和绘制每个精灵的管理员。我同意,这听起来是一样的,但是我更喜欢基于组件的设计,因为我非常喜欢它具有的面向对象的方法。

对于第三个问题,是的,您应该在LoadContent方法中加载任何形式的内容(资产,字体等)。至于初始化,通常可以在Initialize函数中创建Player对象,然后将其内容加载到LoadContent中。或者,也可以根据需要在LoadContent中完成所有操作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.