题
当您拥有使用非常大图像(大于硬件可以支持的图像)的2D游戏时,该怎么办?也许对这个问题有一些有趣的解决方案,这在我之前从未发生过。
我基本上是在从事某种图形冒险游戏的制作。我的目标受众是几乎没有游戏开发(和编程)经验的人。如果您使用的是这样的应用程序,是不是更希望它在内部处理问题而不是告诉您“拆分图像”?
语境
众所周知,图形卡对其可使用的纹理大小施加了一组限制。例如,使用XNA时,取决于您选择的配置文件,最大纹理大小被限制为2048或4096像素。
通常,在2D游戏中这不会带来太大问题,因为大多数游戏都具有可以由较小的单个块(例如,图块或变形的精灵)构建的关卡。
但是,请考虑一些经典的点按式图形冒险游戏(例如Monkey Island)。图形冒险游戏中的房间通常是整体设计的,很少或没有可重复的部分,就像画家在风景上一样。或像《最终幻想7》这样的游戏使用了大型的预渲染背景。
这些房间中的一些可能会变得很大,经常跨越三个或更多屏幕宽度。现在,如果我们在现代高清游戏的背景下考虑这些背景,它们将很容易超过最大支持的纹理大小。
现在,解决此问题的明显方法是将背景分成适合需求的较小部分,并排绘制。但是,您(或您的艺术家)是否应该成为拆分所有纹理的人?
如果您使用的是高级API,它是否应该准备好应对这种情况并在内部进行纹理的拆分和组装(作为XNA的内容管道等预处理程序或在运行时进行)?
编辑
从XNA实现的角度来看,这就是我的想法。
我的2D引擎只需要Texture2D功能的很小一部分。我实际上可以将其简化为以下接口:
public interface ITexture
{
int Height { get; }
int Width { get; }
void Draw(SpriteBatch spriteBatch, Vector2 position, Rectangle? source, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth);
}
我使用的唯一依赖Texture2D的外部方法是SpriteBatch.Draw(),因此我可以通过添加扩展方法在它们之间建立桥梁:
public static void Draw(this SpriteBatch spriteBatch, ITexture texture, Vector2 position, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth)
{
texture.Draw(spriteBatch, position, sourceRectangle, color, rotation, origin, scale, effects, layerDepth);
}
每当我以前使用Texture2D时,这将允许我互换使用ITexture。
然后,我可以创建ITexture的两个不同实现,例如RegularTexture和LargeTexture,其中RegularTexture将仅包装常规的Texture2D。
另一方面,LargeTexture将保留一个Texture2D的列表,每个列表都对应于完整图像的一个分割片段。最重要的部分是,在LargeTexture上调用Draw()应该能够应用所有转换并绘制所有片段,就好像它们只是一个连续图像一样。
最后,为了使整个过程透明,我将创建一个统一的纹理加载器类,该类将充当Factory Method。它将纹理的路径作为参数,并返回一个ITexture,该ITexture可以是RegularTexture或LargeTexture,具体取决于图像大小是否超过限制。但是用户不需要知道它是哪一个。
有点过大或听起来还好吗?