将代码分割成DrawableComponents时,2D相机不起作用

我有下面的相机写的:

public class Camera { public Vector2 Position; Viewport Viewport; public Matrix Transformation { get { return Matrix.CreateTranslation(new Vector3(-this.Position.X, -this.Position.Y, 0)) * Matrix.CreateRotationZ(0f) * Matrix.CreateScale(new Vector3(1f, 1f, 1)) * Matrix.CreateTranslation(new Vector3(Viewport.Width * 0.5f, Viewport.Height * 0.5f, 0)); } } public Camera(GraphicsDevice device) { this.Position = Vector2.Zero; this.Viewport = device.Viewport; } } 

现在,虽然这可以在教程中工作,你可以像GameDraw一样绘制所有的绘图:

 protected override void Draw(GameTime gameTime) { this.GraphicsDevice.Clear(Color.SkyBlue); this.SpriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, null, null, null, cam.Transformation); this.Player.Draw(this.SpriteBatch); this.World.Draw(this.SpriteBatch); this.Enemies.Draw(this.SpriteBatch); this.SpriteBatch.End(); base.Draw(gameTime); } 

当你在DrawableGameComponents(我有)组织你的代码时失败。 现在,从技术角度来说,我可以在游戏中添加相机作为服务,在DrawableGameComponents的构造函数中检索它,在Component中将其添加为字段,然后在每个组件的Draw中编辑spriteBatch.Begin()如上所示。 所以实际上它会是这样的:

 public class TestComponent : DrawableGameComponent { Camera Camera; SpriteBatch Batch; public TestComponent(Game game) : base(game) { this.Camera = (Camera)this.Game.Services.GetService(typeof(Camera)); this.Batch = (SpriteBatch)this.Game.Services.GetService(typeof(SpriteBatch)); } public override void Draw(GameTime gameTime) { this.Batch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, null, null, null, this.Camera.Transformation); // draw the component this.Batch.End(); base.Draw(gameTime); } } 

但是,正如你可能已经猜到,这是一个坏主意,因为它基本上是多余的。

有一种方法可以在中央位置维护这个吗?

我会做下面的基本方法:

你有组件和每个组件types你有一个类与组件做什么。

所以对于这个特定的问题,这意味着你需要一个知道Camera转换的类,并且所有的 Renderables都有一个数据结构(最简单的是一个数组,后面是列表或者树)。

UML风格:

 + configure(Camera OfCamera) + renderAll() - renderRenderable(Renderable OfRenderable) + add(Renderable Component) + remove(Renderable Component) - Array<Renderable> Renderables - Camera OfCamera 

如果您关心构造函数冗余,则可以创建一些基类DGCBase,它将从DrawableGameComponentinheritance,并且每个组件都将inheritance它。 成员(variables,函数,也是构造函数),这是所有组件通用的将在这个DGCBase。 特殊的function将在特定的组件。

但是这个批处理开始将在每个组件中。 也许一段时间后,你会想改变它的参数。 但是我认为这不是很多“复制”的代码。

也许你可以创建一些像BeginDraw和EndDraw(它们是Game类的一部分)的函数,并在每个组件的Draw函数中(开始和结束)调用它们。

答案很简单

在你的游戏代码中:

  public override void Draw(GameTime gameTime) { this.Batch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend, null, null, null, null, this.Camera.Transformation); base.Draw(gameTime); this.Batch.End(); } 

tl; dr:调用Begin,调用base.Draw(),调用End。 在基类Game中,似乎有分配所有组件的Draw和Update方法的逻辑。