绘制等距游戏世界 [英] Drawing Isometric game worlds

查看:21
本文介绍了绘制等距游戏世界的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我已阅读参考资料(例如

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

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

tile_map[][] = [[...],...]for (i = 0; i = 0; j--)://这里改变了循环条件.画(tile_map[i][j],x = (j * tile_width/2) + (i * tile_width/2)y = (i * tile_height/2) - (j * tile_height/2))

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

之字形"方法:

优势:

也许之字形"方法的优势在于渲染的地图可能看起来比菱形"方法在垂直方向上更加紧凑:

缺点:

尝试实现zig-zag技术,缺点可能是编写渲染代码有点困难,因为它不能像嵌套的for循环那样简单地编写数组中的每个元素:

tile_map[][] = [[...],...]for (i = 0; i 

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

注意:此答案中包含的插图是使用所提供的图块渲染代码的 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是指代表瓷砖的图像中地面瓷砖的宽度和高度:

只要图像尺寸和图块尺寸匹配,就可以使用图像的尺寸.否则,瓷砖地图可能会在瓷砖之间出现间隙.

What is the correct way to draw isometric tiles in a 2D game?

I've read references (such as this one) that suggest the tiles be rendered in a way that will zig-zag each column in the 2D array representation of the map. I imagine that they should be drawn more in a diamond fashion, where what gets drawn to the screen relates more closely to what the 2D array would look like, just rotated a little.

Are there advantages or disadvantages to either method?

解决方案

Update: Corrected map rendering algorithm, added more illustrations, changed formating.

Perhaps the advantage for the "zig-zag" technique for mapping the tiles to the screen can be said that the tile's x and y coordinates are on the vertical and horizontal axes.

"Drawing in a diamond" approach:

By drawing an isometric map using "drawing in a diamond", which I believe refers to just rendering the map by using a nested for-loop over the two-dimensional array, such as this example:

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)
        )

Advantage:

The advantage to the approach is that it is a simple nested for-loop with fairly straight forward logic that works consistently throughout all tiles.

Disadvantage:

One downside to that approach is that the x and y coordinates of the tiles on the map will increase in diagonal lines, which might make it more difficult to visually map the location on the screen to the map represented as an array:

However, there is going to be a pitfall to implementing the above example code -- the rendering order will cause tiles that are supposed to be behind certain tiles to be drawn on top of the tiles in front:

In order to amend this problem, the inner for-loop's order must be reversed -- starting from the highest value, and rendering toward the lower value:

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)
        )

With the above fix, the rendering of the map should be corrected:

"Zig-zag" approach:

Advantage:

Perhaps the advantage of the "zig-zag" approach is that the rendered map may appear to be a little more vertically compact than the "diamond" approach:

Disadvantage:

From trying to implement the zig-zag technique, the disadvantage may be that it is a little bit harder to write the rendering code because it cannot be written as simple as a nested for-loop over each element in an array:

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
        )

Also, it may be a little bit difficult to try to figure out the coordinate of a tile due to the staggered nature of the rendering order:

Note: The illustrations included in this answer were created with a Java implementation of the tile rendering code presented, with the following int array as the map:

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

The tile images are:

  • tileImage[0] -> A box with a box inside.
  • tileImage[1] -> A black box.
  • tileImage[2] -> A white box.
  • tileImage[3] -> A box with a tall gray object in it.

A Note on Tile Widths and Heights

The variables tile_width and tile_height which are used in the above code examples refer to the width and height of the ground tile in the image representing the tile:

Using the dimensions of the image will work, as long as the image dimensions and the tile dimensions match. Otherwise, the tile map could be rendered with gaps between the tiles.

这篇关于绘制等距游戏世界的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆