java - 绘制等距墙

标签 java math isometric

我在使用等距墙时遇到了一些麻烦。

我正在使用从后到前的渲染方法绘制等距的地砖,并且效果很好。我还将地板砖正确排列在一个良好的网格中。代码(对于等轴测平面图,这似乎是非常标准的),如下所示:

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

我正在使用它作为我的墙砖:

(它是Google图像搜索中的占位符,但是应该都一样)

这是我得到的结果:



我的墙的渲染顺序显然是正确的,较近的墙在更远的墙之上进行渲染,这是我想要的,但是定位也很不正确,而且我不知道该如何正确地使用它来纠正该问题。像素值。

作为引用,我确实使用了硬编码的像素val进行了试验,因为我发现从一堵墙的右角到下一堵墙的右角,其变化恰好是(200,-100)像素。当我为此做渲染循环帐户时
int xCo = (x+y)*200;
int yCo = (y-x)*-100;

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

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

谢谢!

最佳答案

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

就地板的放置而言,您在地板案例中的x和y坐标表示类似“左/右”和“向前/向后”。对于积木,左和右仍然有意义,但是我们想用上下替换前/后,以反射(reflect)垂直方向。因此我们的“y”有了新的含义。

现在,在数学中,y轴通常指向上方,而在2D计算机图形学中,y轴指向下方。您可以选择-下面的代码假定它指向上方,因此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循环之前的三个常量移出实际的绘图代码-它们仅取决于图像属性和其他常量,不必在每次绘制墙时都需要重新计算。

关于java - 绘制等距墙,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14488989/

相关文章:

javascript - 如何计算 z 轴上的位置

javascript - HTML5 Canvas 生成等距图 block

java - 将字母(char)索引翻译为整数索引 POI Java

java - Spring 4 @controller 配置

java - ReSTLet:应用程序启动前的初始化代码

java - 在 Java 中将弧度转换为度数

c# - 如何渲染和检测视线?

android - 如何创建等距网格android

java - 渲染等距网格

java - DbUnit + springtestdbunit 中的表计数错误