Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 新华社:一个简单的方法只使用一个spritebatch?_C#_Xna_Xna 4.0 - Fatal编程技术网

C# 新华社:一个简单的方法只使用一个spritebatch?

C# 新华社:一个简单的方法只使用一个spritebatch?,c#,xna,xna-4.0,C#,Xna,Xna 4.0,很多时候,我都在想,是否有一种简单的方法可以在XNA中只使用一个spritebatch,我发现微软的内置组件系统是一个好主意,但构建起来相当神秘 我只能假设XNA的很多方式都是由于向后兼容性或Xbox兼容性,这本身并不是坏事,我确信有些细节导致事情按照现在的方式发展,但主系统可能看起来有点神秘。这是我一直认为的,直到我意识到游戏服务的真正目的和功能,以及它们与装箱/拆箱和.Net类型系统的链接 我承认微软的一个缺点是他们缺乏创造性的命名。起初,我一直认为游戏服务与系统服务相连,或者服务是某种特殊

很多时候,我都在想,是否有一种简单的方法可以在XNA中只使用一个spritebatch,我发现微软的内置组件系统是一个好主意,但构建起来相当神秘


我只能假设XNA的很多方式都是由于向后兼容性或Xbox兼容性,这本身并不是坏事,我确信有些细节导致事情按照现在的方式发展,但主系统可能看起来有点神秘。

这是我一直认为的,直到我意识到游戏服务的真正目的和功能,以及它们与装箱/拆箱和.Net类型系统的链接

我承认微软的一个缺点是他们缺乏创造性的命名。起初,我一直认为游戏服务与系统服务相连,或者服务是某种特殊的类或接口

事实上,游戏的服务集合只不过是对象的集合。这些服务允许连接到游戏的任何游戏组件从游戏中检索数据

SpriteBatch就是一个例子。通过向游戏的服务中添加SpriteBatch,并将其注册为typeofSpriteBatch,任何组件都可以通过将typeofSpriteBatch提供给GetService方法,从服务中提取SpriteBatch

下面是一些未测试的示例代码,只是一个示例:

public namespace MyGame
{
  public class MainGame:Game
  {
    SpriteBatch spriteBatch;
    protected override void Initialize()
    {
      spriteBatch = new SpriteBatch(GraphicsDevice);
      Services.AddService(typeof(SpriteBatch), spriteBatch);
      base.Initialize();
    }
  }
  public class DrawableComponent : DrawableGameComponent
  {
    SpriteBatch spriteBatch;
    public override void Initialize()
    {
      spriteBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
      if(spriteBatch == null)
      { throw new Exception("No SpriteBatch found in services"); }
    }
  }
}
我这里的例子也说明了一个被忽视的因素。 微软的默认游戏模板将SpriteBatch创建放在加载内容方法中,这让许多人相信它必须保留在那里。事实上,您可以自由地将其向前移动,直到初始化方法,而不是构造函数,这意味着可以在初始化任何组件之前将其移动到服务中,从而确保所有在其初始化方法中从服务中寻求SpriteBatch的组件都将获得SpriteBatch

请务必注意,当添加到服务时,如果给定的项为null,则会引发异常,而从中获取的项不会引发异常,它只会返回null并继续执行,因此必须尽快执行null检查。还要注意的是,如果一个组件是在游戏中期创建的,它将不会被调用其初始化,因此必须通过某种方式进行补偿

此技术的更多示例可在此处找到:

制作您自己的基类,替换DrawableGameComponent和相关的基础设施-基本上有一个列表。 修改该基类的Draw方法以获取SpriteBatch参数。 利润
请参阅讨论,并详细解释为什么这是一个好主意以及GameComponent和IServiceProvider的真正用途。

一些澄清:除非您将值类型放入服务中,否则不会进行装箱/拆箱操作—这是一件非常奇怪的事情。和GameComponent。在游戏开始后,当该组件添加到组件中时,会调用Initialize。请注意,在调用LoadContent之前,不应访问GraphicsDevice。如果图形设备被重置,例如:游戏最小化或用户桌面被锁定,并且自动资源重新创建因任何原因失败,则会再次调用LoadContent方法,但不会初始化,以手动重新创建图形资源。您仅在Initialize中创建的任何内容都将保持无效,如果您使用它,则将崩溃。它们与可能使用值类型的链接是链接。我不知道最后一个,我以前从未注意到它发生过,所以我必须调查一下。至于图形设备问题,这没什么大不了的,有很多解决方法。我认为正确的解决方法可能包括编写某种ISpriteBatchService,类似于IGraphicsDeviceService,并以几乎相同的方式使用它。尽管我认为一个好的ISpriteBatchService接口会更复杂,但SpriteBatch是有状态的,而GraphicsDevice则不是这样。