小编典典

绘制等距游戏世界

all

在 2D 游戏中绘制等距图块的正确方法是什么?

我已阅读参考资料(例如this one),这些参考资料建议以一种将地图的二维数组表示中的每一列锯齿形呈现的方式呈现图块。我想它们应该更多地以菱形方式绘制,在屏幕上绘制的内容与 2D
阵列的外观更密切相关,只需旋转一点。

两种方法都有优点还是缺点?


阅读 67

收藏
2022-08-07

共1个答案

小编典典

更新:更正了地图渲染算法,添加了更多插图,更改了格式。

或许“之字形”技术将图块映射到屏幕的优势可以说是图块xy坐标位于垂直轴和水平轴上。

“绘制钻石”方法:

通过使用“绘制菱形”绘制等距地图,我认为这指的是通过for在二维数组上使用嵌套循环来渲染地图,例如这个例子:

tile_map[][] = [[...],...]

for (cellY = 0; cellY < tile_map.size; cellY++):
    for (cellX = 0; cellX < tile_map[cellY].size cellX++):
        draw(
            tile_map[cellX][cellY],
            screenX = (cellX * tile_width  / 2) + (cellY * tile_width  / 2)
            screenY = (cellY * tile_height / 2) - (cellX * tile_height / 2)
        )

优势:

该方法的优点是它是一个简单的嵌套for循环,具有相当直截了当的逻辑,可以在所有图块中始终如一地工作。

坏处:

这种方法的一个缺点是地图上图块的坐标xy坐标将在对角线上增加,这可能会使将屏幕上的位置直观地映射到表示为数组的地图变得更加困难:

平铺地图的图像

然而,实现上面的示例代码会有一个陷阱——渲染顺序将导致应该在某些图块后面的图块被绘制在前面的图块之上:

不正确的渲染顺序产生的图像

为了修正这个问题,内部for循环的顺序必须颠倒——从最高值开始,向着较低的值渲染:

tile_map[][] = [[...],...]

for (i = 0; i < tile_map.size; i++):
    for (j = tile_map[i].size; j >= 0; j--):  // Changed loop condition here.
        draw(
            tile_map[i][j],
            x = (j * tile_width / 2) + (i * tile_width / 2)
            y = (i * tile_height / 2) - (j * tile_height / 2)
        )

通过上述修复,应该更正地图的渲染:

从正确的渲染顺序生成的图像

“之字形”方法:

优势:

也许“之字形”方法的优点是渲染的地图可能看起来比“菱形”方法更垂直紧凑:

锯齿形渲染方法看起来很紧凑

坏处:

尝试实现之字形技术的缺点可能是编写渲染代码有点困难,因为它不能像for在数组中的每个元素上嵌套循环一样简单:

tile_map[][] = [[...],...]

for (i = 0; i < tile_map.size; i++):
    if i is odd:
        offset_x = tile_width / 2
    else:
        offset_x = 0

    for (j = 0; j < tile_map[i].size; j++):
        draw(
            tile_map[i][j],
            x = (j * tile_width) + offset_x,
            y = i * tile_height / 2
        )

此外,由于渲染顺序的交错性质,尝试找出图块的坐标可能有点困难:

锯齿形订单渲染上的坐标

注意:此答案中包含的插图是使用所提供的瓷砖渲染代码的 Java 实现创建的,使用以下int数组作为地图:

tileMap = new int[][] {
    {0, 1, 2, 3},
    {3, 2, 1, 0},
    {0, 0, 1, 1},
    {2, 2, 3, 3}
};

平铺图像是:

  • tileImage[0] ->一个盒子,里面有一个盒子。
  • tileImage[1] ->一个黑匣子。
  • tileImage[2] ->一个白色的盒子。
  • tileImage[3] ->一个盒子,里面有一个高大的灰色物体。

关于瓷砖宽度和高度的说明

上述代码示例中使用的变量tile_widthtile_height是指表示地砖的图像中地砖的宽度和高度:

显示平铺宽度和高度的图像

只要图像尺寸和图块尺寸匹配,使用图像的尺寸就可以了。否则,瓷砖地图可能会被渲染为瓷砖之间的间隙。

2022-08-07