在XNA 4.0的drawableGameComponent中传递参数的方法是什么?

我有一个小的演示,我想创建一个类,在屏幕上绘制消息像fps率。 我正在阅读一本XNA书,他们评论GameComponents。 我创建了一个inheritanceDrawableGameComponent的类

public class ScreenMessagesComponent : Microsoft.Xna.Framework.DrawableGameComponent 

我重写了一些像Initialize或LoadContent的方法。 但是当我想重写绘制我有一个问题,我想传递给它的一些参数。

重写的方法不允许我传递参数。

  public override void Draw(GameTime gameTime) { StringBuilder buffer = new StringBuilder(); buffer.AppendFormat("FPS: {0}\n", framesPerSecond); // Where get framesPerSecond from??? spriteBatch.DrawString(spriteFont, buffer.ToString(), fontPos, Color.Yellow); base.Draw(gameTime); } 

如果我用参数创建一个方法,那么我不能覆盖它,不会自动调用:

  public void Draw(SpriteBatch spriteBatch, int framesPerSecond) { StringBuilder buffer = new StringBuilder(); buffer.AppendFormat("FPS: {0}\n", framesPerSecond); spriteBatch.DrawString(spriteFont, buffer.ToString(), fontPos, Color.Yellow); base.Draw(gameTime); } 

所以我的问题是:

  • 有没有一个机制将parameter passing给drawableGameComponent? 最佳做法是什么?
  • 一般来说,使用GameComponents是一个很好的做法?

给你的DrawableGameComponent一些属性,例如framesPerSecond,你在调用Draw(GameTime)之前设置。 这可能只适用于属性是组件的“自然”部分。

另一种select是使用游戏服务机制。 游戏服务是维持需要彼此交互的对象之间松散耦合的机制。 将服务类添加到游戏服务容器;

  //this is usually in the Game.Initialize() Services.AddService(typeof(ContentManager), Content); Services.AddService(typeof(Camera), camera); 

DrawableGameCompontent对象可以通过服务提供者访问该服务对象;

 //DrawableGameComponent method public void Draw(GameTime gt) { Camera camera = (Camera)Game.Services.GetService(typeof(Camera)); foreach (ModelMesh mesh in invaderModel.Meshes) { foreach (BasicEffect effect in mesh.Effects) { //Effect Settings Goes here effect.LightingEnabled = true; effect.EnableDefaultLighting(); effect.World = world; effect.Projection = camera.Proj; effect.View = camera.View; } mesh.Draw(); } } 

这个问题有一个关于使用GameComponents的利弊的有趣的讨论。

主要有两种方式:

  1. 正如路易斯·埃斯特拉达(Luis Estrada)所说的那样,添加逻辑来计算组件的Update-和Draw-Calls(这个数字可能不同)。 如果没有其他组件需要这个属性,这可能是最好的方法。
  2. 如果其他组件也需要了解当前的帧率,那么实现一个负责这个的GameService可能是一个好方法。 在ScreenMessagesComponent的每个DrawCall中访问Service并将值绘制到屏幕上。

看看这个计算帧率: 计算游戏中每秒的帧数

我已经在堆栈溢出回答了一个非常类似的问题。 总结:

将parameter passing给游戏组件方法的最好方法是将parameter passing给! 不幸的是,这排除了GameComponent的使用 – 因为它的接口是固定的。 这是一个相当弱的API。

最好把GameComponent当作你如何在游戏中设置“游戏组件”或“角色”系统的例子 。 像XNA的许多其他部分(精灵字体,模型, Game类本身等) – 你能够并鼓励他们取代它,如果你需要的function,它不提供。

虽然听起来你根本不需要演员或组件系统。 我想你所拥有的每个“组件”都需要传入不同的数据? 简单地用Draw方法创建一个类? 看看这个答案 。


但是,如果您必须使用GameComponent ,那么可能下一个最好的方法是在其Draw和/或Update方法被调用之前在GameComponent上设置成员属性或字段(他们在Game.DrawGame.Update被调用 – 所以在哪里你可以在你自己的游戏类中调用base.Drawbase.Update )。

(可以使用其他方法,只要做最简单的事就行了 。)

问题是像GameComponent有一个固定的接口; 你不能把它作为一个论点。 因此,你可以做的是创建一个新的项目,作为主游戏类中的服务。 然后,将其添加到您的游戏服务中,并在您需要绘制时尝试获取它。

所以,在你的游戏开始(构造函数或Initialize方法,无论什么作品)你可以做:

 DebugInformer informer = new DebugInformer(); Services.AddService(typeof(DebugInformer), informer); 

DebugInformer是您自己devise的一类。 给它的属性,为你工作像FramesPerSecond 。 你可以添加你想要的特定于你的游戏的其他东西,比如ItemsOnGround和其他任何适合你的东西。 在代码的后面,你可以得到这些属性,并像这样使用它们:

 //In the middle of your specific Component's draw call: DebugInformer informer = Game.Services.GetService(typeof(DebugInformer)) as DebugInformer; if (informer != null) { // Informer is present, use informer.FramesPerSecond and other stuff } 

服务是为了这样的问题而devise的,所以不要害怕使用它。

祝你好运!