具有预定偏移/旋转的分层精灵

3
可能不是很描述性的标题,但我会尽力。这是我第一次在StackOverflow上发布问题,我对使用C#编程还相对较新(一年前开始使用Unity,几天前决定升级到XNA)。话虽如此,请对我友善。
我正在规划一个2D游戏的机制,虽然在XNA中玩了一段时间后,大部分内容似乎都很简单,但有一个问题一直困扰着我,而且至今没有令人满意的答案。该问题涉及将精灵层叠成复合/复杂精灵。例如,游戏中的一个角色可能持有任意数量的武器之一或两者皆有。我进行了一些关于此主题的研究,并发现有人建议使用RenderTarget类将一系列精灵绘制为一个精灵,有人则建议在Draw()期间简单地将精灵放在彼此之上。然而,这些主题主要集中在游戏中只有单个角色的相对简单情况。
在我的情况下,游戏将具有许多基于精灵的角色,这些角色具有完全不同的姿势/动画。现在大约有10个角色,开发后可能会添加更多。同样会有许多武器(可能会有20支开始)组合到角色上。我对此感到很自在。然而,问题是每个角色都需要在每个动画帧中以不同的位置和不同的旋转方式绘制武器精灵。
我考虑了几种方法来解决这个问题,但它们都有非常大的缺点。
第一种方法只是为每个角色的每个武器绘制一个精灵表,该表的大小与相应的角色相同。这种方法的好处是轻松添加调用以在基础角色之上绘制其他精灵,而无需进行任何计算。缺点是将创建过多的额外精灵表(10个角色x 20个武器= 200个额外的表)。
第二步是创建一个用于处理武器精灵的类,WeaponSprite类将附加到每个武器的单个纹理上,然后根据其所附加到的角色来存储有关绘制时使用的偏移/旋转信息。但是,按每帧基础组织偏移/旋转会非常繁琐,我无法想到任何轻松的方法来获取所需的帧相关信息(我的想法是创建一个AnimationFrame类来跟踪每个角色的动画名称、方向和帧编号,然后在武器类中使用字典根据当前帧的名称加载正确的数据,但这个想法似乎很不明智)。该方法还具有需要相对较大的内存来实现的缺点(假设Vector2为8字节且float为4字节,在当前使用的帧数下,有10个角色和20个武器需要192KB的内存,随着添加更多武器,这个数字只会变得越来越大)。我有一个类似的想法(我从其他帖子中窃取了一些关于同一主题的内容),即使用保留的alpha值像素来链接偏移和每个武器的“起点”,在运行时计算位置,然后只需在前述的字典中存储旋转浮点数。由于我对XNA(还有C#)不是很熟悉,所以我想发帖让专家们参与。我的方法是否正确,或者我是否忽略了一些非常简单的东西?非常感谢您的帮助,并请告诉我如果需要任何其他信息。
1个回答

2
哇,大问题。我无法告诉您如何实现这一点,但我可以给您一些有用的建议:
建议#0:每当出现任何类型的合成问题时,人们都会推荐“渲染目标”作为某种合成万灵药,但通常是错误的。如果可以避免使用渲染目标,请尽量避免使用它们。只有在对最终合成图像进行效果(混合、模糊等)时才需要它们。否则,直接将精灵绘制在彼此之上以直接到后备缓冲区即可。
建议#1:如果可能,要将所有精灵打包到单个精灵表中。如果超过纹理大小限制,则必须聪明地将精灵分区跨越表格。原因是性能-您希望限制纹理交换的数量-请参阅 此答案以获取详细信息
您可以尝试使用适用于XNA的现有精灵打包程序。如果找到合适的程序,请使用它。良好的程序将允许您在调用SpriteBatch.Draw时像处理纹理一样处理打包的精灵。
建议 #2:不要担心定位数据在运行时占用了多少空间。192kb 几乎微不足道,就像一个小纹理的大小。
这意味着,可以尽可能多地存储定位元数据,并避免重复使用纹理。
如何存储元数据几乎无关紧要。
建议 #3:可以将存储需求和内容创建从 n×m 问题变为 n+m 问题(n 个角色和 m 个武器)。只需将武器仅存储为“起点”,并将角色存储为“起点”和“手部位置和旋转”。只需简单计算,使武器的起点与角色的手部对齐即可。
然后,您可以添加角色而不必担心有哪些武器存在,也可以添加武器而不必担心有哪些角色存在。
这是一个需要多少空间的示例:10个字符×20字节+20个武器×8字节= 360字节。非常小!(尽管您可能需要更多的附件点-不同种类的武器,帽子等等。编辑:糟糕,我没有包括动画帧-但它仍然是相对较小的数据量。)
建议#4:正如您在帖子中所暗示的那样,最棘手的部分是内容创建。
正如您所暗示的那样,理想情况下,您希望能够直接在图像编辑器中编辑附件点。这是一个引人入胜的想法。特殊的alpha值只适用于您的精灵没有反锯齿的情况。您可以从图层和不同颜色中理论上做一些事情。最难的部分是弄清楚如何编码旋转。
您可以使用XNA内容管道处理器在构建时从图像中提取数据。然而,这变得非常昂贵(特别是如果您以前没有做过-内容管道文档不足)。除非您的艺术需求真的非常巨大,否则几乎肯定不值得额外的开发时间来制作内容管道扩展。到您完成时,您可以手动编写定位数据数次。
我的建议是将额外的数据存储在易于编辑的XML文件中。我建议使用XNA的XML内容导入器。一开始可能会有些难以掌握格式,而且你必须记得包含适当的程序集引用。但是一旦你知道如何使用它,这是最快捷的将结构化数据快速导入XNA的方法。

哇,谢谢你的帖子!我想我会逐点回复。 - Roy Ermak
5分钟后就不能编辑了吗?不管怎样,这些内容对我非常有帮助;现在我知道如果没有必要的话,暂时不用去管内容管道。由于涉及到精灵/武器,我觉得将旋转数据存储在角色上可能会无效,因为它很容易被武器和角色改变,但从数据方面来看并不重要。我想我只是有点担心内存使用量会增加,觉得192kb有点大。我会研究XNA,并计划在某个时候做一个单一的精灵表。 - Roy Ermak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接