9

我在使用等距墙时遇到了一些问题。

我正在使用从后到前的渲染方法绘制等距地砖,并且效果很好。我还保持我的地砖在一个漂亮的网格中正确排列。代码(这似乎是等距平面图的标准)如下:

for(int x = 0; x < 6; x++){
    for(int y  = 3; y >=0 ; y--){

        int xCo = (y+x)*(tileWidth/2);
        int yCo = (x-y)*(tileHeight/2);
        tile.draw(g, xCo, yCo);
    }            
}

这是一个不错的小地板:

多块地砖

网格是从这个图块构建的:

单瓦

不幸的是,当我对墙壁使用相同的逻辑时,一切都变得糟糕透顶。

for(int x = 0; x < 6; x++){
    for(int y  = 3; y >= 0 ; y--){

        int xCo = (y+x)*(wallWidth()/2);
        int yCo = (x-y)*(wallHeight()/2);
        walls.draw(g, xCo, yCo);    
}
}

我用这个作为我的墙砖:

单墙砖

(它是来自谷歌图片搜索的占位符,但它应该可以正常工作)

这是我得到的结果:

多块墙砖

我的墙壁的渲染顺序显然是正确的,较近的墙壁在较远的墙壁上渲染,这是我想要的,但定位也非常不正确,我不知道我应该如何纠正这个不足像素值。

作为参考,我确实使用硬编码的像素值进行了试验,因为我发现从一堵墙的右上角到另一堵墙的右角,变化正好是 (200, -100) 像素。当我为此制作渲染循环时

int xCo = (x+y)*200;
int yCo = (y-x)*-100;

它工作得很好,但这不是一个可行的解决方案,因为它不允许任何多功能性。

因此,寻找有关如何使我的等距墙对齐的建议。我究竟做错了什么?

谢谢!

4

3 回答 3

2

您不能简单地对墙壁和地板使用相同的绘图代码,因为墙壁和地板不在同一平面上:地板是平的(水平的)而墙壁是垂直的。所以你必须稍微不同地绘制它们。

就瓷砖的放置而言,您在地板案例中的 x 和 y 坐标意味着“左/右”和“前/后”。对于砖块来说,left 和 right 仍然有意义,但我们希望将 forward/backward 替换为 up 和 down 以反映垂直方向。所以我们的“y”有了新的含义。

现在,在数学中,y 轴通常指向上方,而在 2D 计算机图形中则指向下方。您可以选择 - 下面的代码假定它指向上方,这y = 0意味着“在地板上”。

所以让我们开始考虑顺序。您发布的示例砖是用于作为地板(上)左端的墙。由于砖的黑色部分(墙的深度),我们必须确保首先绘制更靠右的砖,以便左侧的黑色深度会被更近的砖覆盖。相同的论点适用于墙壁顶部的黑色,我们必须先绘制较低的砖块。

如果我们坚持前面讨论的 x 和 y 方向(x 从左到右,y 从下到上),这意味着我们必须在负方向上运行两个 for 循环:

    for (int y = 3; y >= 0; y--) {
        for (int x = 5; x >= 0; x--) {
            ...
        }
    }

现在的主要问题是我们必须将每块砖相对于其他砖的绘制偏移多少。让我们一次只做一个方向,从 x 方向开始。

让我们想象一下只有两块相邻的砖块:

两块砖水平

两者的左侧有可见的黑色深度部分,但右侧不应该显示它。因此,我们不能简单地将正确的图像偏移 PNG 的整个宽度。事实上,假设砖与你的地砖对齐,墙的实际前部的宽度应该是瓷砖宽度的一半。

int xCo = x * tileWidth / 2;

左边的黑色墙体深度不能忽略,因为我们可能想让每块砖向左偏移一点,这样墙前角的x坐标就和地砖对齐了,而不是x-后角的坐标。

现在,每块砖的 y 坐标有点棘手,因为它不仅取决于砖的行,还取决于 x 坐标:越靠右,我们应该画得越高。但是让我们暂时忽略 x 方向并尝试简单地绘制一列砖块:

两块砖垂直

同样,两块砖的 y 坐标之间的增量不是 PNG 的全高。与我们假设砖块与允许我们tileWidth用作 delta-x 的砖块对齐的左/右案例不同,砖块可以具有任意高度。但是我们仍然可以从图像高度计算出实际的砖高度,因为我们知道左侧的深度和顶部的深度必须对齐。

如果我们看一下砖PNG右上角的小透明三角形,我们注意到它的宽度和高度的比例必须与地砖的宽度和高度的比例相同。这允许我们从上面计算的 xoffset 计算 yoffset,并使用它来推断砖的实际高度:

int yoffset = xoffset * tileHeight / tileWidth;
int wallHeight = wallHeight() - tileHeight / 2 - yoffset;

请注意,这仅在 PNG 的边界没有空白空间的假设下有效,并且由于舍入错误可能仍会失败。因此,如有必要,您可以在此处添加Math.ceil()(或简单地)。+ 1

所以对于简单的列,我们现在可以开始了:我们可以简单地将我们的y变量与上面的wallHeight. 但如前所述,砖块的 x 位置也会影响 y 像素坐标。如果我们再看第一张图片,两块砖并排在一起,我们需要将右边的砖向上移动多少才能与左边的砖对齐?嗯,这个其实很简单,因为它和地砖一样:只有地砖的一半高度!

所以我们都准备好了。如果我们把所有东西放在一起,我们最终会得到一些像这样的代码:

int xoffset = wallWidth() - tileWidth / 2;
int yoffset = xoffset * tileHeight / tileWidth;
int wallHeight = wallHeight() - tileHeight / 2 - yoffset;

for (int y = 3; y >= 0; y--) {
    for (int x = 5; x >= 0; x--) {

        int xCo = x * tileWidth / 2;
        int yCo = y * wallHeight - x * tileHeight / 2;

        walls.draw(g, xCo - xoffset, yCo - yoffset);
    }
}

(我假设 wallWidth() 和 wallHeight() 返回砖块 PNG 的宽度和高度。)

请注意,for 循环之前的三个常量可以从实际绘图代码中移出——它们只依赖于图像属性和其他常量,不必在每次绘制墙壁时都重新计算。

于 2013-01-23T23:43:24.730 回答
0

如果您查看形状像菱形的地砖,将其向上移动一半宽度并穿过一半长度,两条边将对齐。
墙砖不是菱形,因此通过移动一半宽度和一半长度,您想要匹配的边缘将不会对齐。

给定u= 移动距离和v= 向上移动距离和A等距角

v = u*tan(A)

u在这种情况下是图像正面的宽度。

如果墙壁图像的面(纹理位)与地砖的边缘长度匹配,则给出

int offset = ?;// this is the width of the black stripe on the image.

for(int x = 0; x < 6; x++){
    for(int y  = 3; y >=0 ; y--){

        int xCo = ((y+x+1)*(tileWidth/2))-offset;
        int yCo = (x-y)*(tileHeight/2);
        wall.draw(g, xCo, yCo);
    }            
}
于 2013-01-23T21:42:58.057 回答
0

在等距领域中,您可以移动三个轴 - Z 表示上下,X 和 Y 表示“对角线”。

首先,让我们想象一个 1 x 1 x 1 单位的等距立方体的像素表示,所有边都表示相同的长度:

它在 Z 轴上将是 A 像素高。它的其他边缘的长度也是 A 像素,但旋转了 60 度 - 所以它将是 sin(30)*A 像素高和 cos(30)*A 像素在 X 和 Y 方向上长 - 也就是 0.5*A 和 sqrt (3)/2 *A。

因此,要在 X、Y 和 Z 中定位等距立方体大小的对象,我们必须通过以下方式在屏幕 x 和 y 上平移它:

y += Z*A
x += X*A/2 - Y*A/2
y += (X+Y)*A*sqrt(3)/2

只要我做出的假设成立,这应该有效。

编辑:顺便说一句,如果图像具有深度,则必须对 A 进行硬编码,因此您无法从图像尺寸中自动提取 A。

于 2013-01-23T22:03:54.843 回答