Java 绘制等距墙

Java 绘制等距墙,java,math,isometric,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.dr

我在等轴测墙方面遇到了一些问题

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

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);
    }            
}
它工作得很好,但这不是一个可行的解决方案,因为它不允许任何通用性

因此,寻找如何使我的等轴测墙对齐的建议。我做错了什么


谢谢

如果你看一看菱形的地砖,将其向上移动一半宽度,然后再移动一半长度,两条边就会对齐。
墙砖不是菱形,因此通过移动一半宽度和一半长度,您要匹配的边将不会对齐。

给定的
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);
    }            
}
int offset=?;//这是图像上黑色条纹的宽度。
对于(int x=0;x<6;x++){
对于(int y=3;y>=0;y--){
int xCo=((y+x+1)*(tileWidth/2))-偏移量;
int yCo=(x-y)*(tileHeight/2);
墙图(g、xCo、yCo);
}            
}

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

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

它将是Z轴上的一个像素高。 它的其他边缘的长度也将是一个像素,但旋转了60度-因此它将是sin(30)*A像素高,cos(30)*A像素长,在X和Y方向-aka,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。

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

地板案例中的x和y坐标在瓷砖放置方面表示“左/右”和“向前/向后”。对于砖块,左侧和右侧仍然有意义,但我们希望用“向上”和“向下”替换“向前/向后”,以反映垂直方向。所以我们的“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相乘int xCo = x * tileWidth / 2;
int yoffset = xoffset * tileHeight / tileWidth;
int wallHeight = wallHeight() - tileHeight / 2 - yoffset;
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);
    }
}