我正在开发2D RPG,它将具有通常的地牢/城镇地图(预先生成)。
我正在使用图块,然后将它们结合起来制作地图。我最初的计划是使用Photoshop或其他一些图形程序组装瓷砖,以便获得一张更大的图片,然后将其用作地图。
但是,我在一些地方读过人们在谈论他们如何使用数组在引擎中构建地图(因此,您向引擎提供了x个tile数组,并将它们组装成地图)。我能理解它是如何完成的,但是实现起来似乎要复杂得多,而且看不到明显的优点。
最常用的方法是什么,每种方法的优点/缺点是什么?
我正在开发2D RPG,它将具有通常的地牢/城镇地图(预先生成)。
我正在使用图块,然后将它们结合起来制作地图。我最初的计划是使用Photoshop或其他一些图形程序组装瓷砖,以便获得一张更大的图片,然后将其用作地图。
但是,我在一些地方读过人们在谈论他们如何使用数组在引擎中构建地图(因此,您向引擎提供了x个tile数组,并将它们组装成地图)。我能理解它是如何完成的,但是实现起来似乎要复杂得多,而且看不到明显的优点。
最常用的方法是什么,每种方法的优点/缺点是什么?
Answers:
首先,我要说的是2D RPG几乎是我亲爱的,并且与旧的DX7 VB6 MORPG引擎一起工作(别笑了,那是8年前了,现在:-))是首先让我对游戏开发产生兴趣的。最近,我开始将在其中一个引擎中开发的游戏转换为使用XNA。
就是说,我的建议是对地图使用分层的基于图块的结构。使用您使用的任何图形API,都会限制可以加载的纹理大小。更不用说显卡纹理内存限制。因此,考虑到这一点,如果您要最大化地图的大小,同时不仅要最小化加载到内存中的纹理的数量和大小,还要减少用户硬盘驱动器上的资产大小和加载时间,肯定会想与瓷砖。
就实现而言,我已经在GameDev.SE和我的博客(均在下面链接)中的一些问题上详细介绍了如何处理它,这与您的要求不完全相同,因此我只是在这里介绍基础知识。我还将记下磁贴的功能,这些磁贴使它们比加载多个大型预渲染图像更有利。如果不清楚,请告诉我。
好的,既然您已经将tilesheet分成了一系列单元格(数字),则可以将这些数字插入到您喜欢的任何容器中。为了简单起见,您只能使用2D阵列。
int[,] mapTiles = new int[100,100]; //Map is 100x100 tiles without much overhead
接下来,您要绘制它们。您可以使这批处理更有效(取决于地图大小)的方法之一是仅计算摄像机当前正在查看的单元格,并在这些单元格之间循环。您可以通过获取相机左上角(tl
)和右下角()的地图图块阵列坐标来实现br
。然后从tl.X to br.X
和循环,tl.Y to br.Y
以嵌套循环的方式绘制它们。下面的示例代码:
for (int x = tl.X; x <= br.X;x++) {
for (int y = tl.Y; y <= br.Y;y++) {
//Assuming tileset setup from image
Vector2 tilesetCoordinate = new Vector2((mapTiles[x,y] % 8) * 32,(mapTiles[x,y] / 8) * 32);
//Draw 32x32 tile using tilesetCoordinate as the source x,y
}
}
注意:我忽略了世界坐标的概念(这是您相机的位置所基于的概念),因为我认为这不在此答案的范围内。您可以在GameDev.SE上阅读有关内容。
我的Tile-Engine资源
注意:所有这些都是针对XNA的,但是它几乎适用于所有内容-您只需要更改绘图调用即可。
其他平铺引擎资源
基于图块的系统和静态模型/纹理系统都可以用来表示一个世界,并且每个都有不同的优势。一个人是否比另一个人更好,可以归结为您如何使用这些组件,以及哪种组件最适合您的技能和需求。
话虽如此,两个系统都可以单独使用,也可以一起使用。
基于标准图块的系统具有以下优点:
切片的缺点是您必须创建一个用于构建基于切片的数据的系统。您可以创建一个将每个像素用作图块的图像,从而从纹理创建2D阵列。您也可以创建专有格式。使用位标志,您可以在相当小的空间中为每个图块存储大量数据。
大多数人做图块的主要原因是因为它允许他们创建小资产并重新使用它们。这使您可以创建更大的图片,并将较小的片段。因为您不需要更改整个世界地图以进行小的更改,所以可以减少返工。例如,如果您想更改所有草的阴影。在大图中,您将必须重新粉刷所有草皮。在图块系统中,您只需更新草砖。
总而言之,与大型图形地图相比,使用基于图块的系统进行的返工可能要少得多。即使不将其用于地面地图,也可能最终使用基于图块的系统进行碰撞。仅仅因为您在内部使用了图块并不意味着您就不能使用模型来表示环境对象,该对象可能为其空间使用多个图块。
您需要提供有关环境/引擎/语言的更多细节,以提供代码示例。
绘制地图:图块在引擎上很容易,因为这样地图就可以表示为巨大的图块索引数组。绘制代码只是一个嵌套循环:
for i from min_x to max_x:
for j from min_y to max_y:
Draw(Tiles[i][j], getPosition(i,j))
对于大型地图,整个地图的一个巨大的位图图像可能会占用大量内存,并且可能大于图形卡支持的单个图像大小。但是您不会对图块产生任何问题,因为您只需为每个图块分配一次图形内存(或者,如果它们全部都在一张纸上,则最好分配一个总计)
重用图块信息进行冲突也很容易。例如,要获得角色小精灵左上角的地形图块:
let x,y = character.position
let i,j = getTileIndex(x,y) // <- getTileIndex is the opposite function of getPosition
let tile = Tiles[i][j]
假设您需要检查是否与岩石/树木等发生了碰撞。您可以在(字符位置+字符精灵大小+当前方向)的位置获取图块,并检查其是否标记为可行走或不可行走。