将笛卡尔的宽度和高度转换为等距

convert Cartesian width and height to Isometric

本文关键字:转换 高度 笛卡尔      更新时间:2023-10-16

我正在尝试在SDL图形库中创建一个等距游戏。

当你在SDL中渲染时,你需要一个源矩形和一个目标矩形。源矩形是你加载的纹理中你想要渲染的部分,目标矩形是你要渲染的屏幕上的区域。矩形仅由4个属性组成,X位置,Y位置,宽度和高度。

现在假设我有一个笛卡尔目标矩形,它的坐标是:

X=20, Y=10, Width=16, Height=16

现在我想把它转换成等距。要转换X和Y坐标,我将使用:

isometricX = cartX - cartY;
isometricY = (cartX + cartY) / 2;

现在我不明白的是,我该如何将笛卡尔宽度和高度转换为等距宽度和高度,以创建视图端口向一侧移动45度,向下移动30度的错觉,从而创建等距外观。

编辑:我想澄清一下我的问题,所以当我把笛卡尔坐标转换成等距坐标时,我改变这个:https://i.stack.imgur.com/I79yK.png: https://i.stack.imgur.com/ZCJg1.png。所以现在我想弄清楚如何旋转这些贴片,使它们都适合在一起以及我需要如何调整高度和宽度来实现这一点

首先,您需要将这些操作转换为等距坐标:

isoX = carX + carY;
isoY = carY - carX / 2.0;
carX = (isoX - isoY) / 1.5;
carY = isoX / 3.0 + isoY / 1.5;

左上角和右下角的直角变为120度,另外两个角变为60度。右下角变成了底角,左上角变成了顶部。这还假设y向上增加,x向右增加(如果您的系统不同,请相应地翻转符号)。您可以通过替换来验证这些操作是否互为逆。

对于一个矩形,你需要4个点转换-角-因为它们不会是"矩形"的SDL的目的(它将是一个平行四边形)。用数字表示更容易理解。

首先,为角指定某种名称。我更喜欢从左下角开始顺时针-这个坐标应该被称为C1,并有关联的X1和Y1,其他的将是C2-4。

C2 - C3
|    |
C1 - C4

然后计算它们的笛卡尔坐标…

X1 = RECT.X;
Y1 = RECT.Y;
X2 = X1; // moving vertically
Y2 = RECT.Y + RECT.HEIGHT;
X3 = RECT.X + RECT.WIDTH;
Y3 = Y2; // moving horizontally
X4 = X3; // moving vertically
Y4 = RECT.Y;

,最后分别对每个坐标应用变换,得到I1, I2, I3, I4坐标…

iX1 = X1 + Y1;
iY1 = Y1 - X1 / 2.0;
// etc

你最终得到的是屏幕坐标I1-4,它的形状是:

    I2
  /    
I1      I3
      /
    I4

但与这种粗制粗制的描述不同,I4和I2的角度将是~127度,I1和I3的角度应该是~53度(这可以微调到恰好60/120,并且取决于计算isoY时carX的2.0因子-它应该是根号(3)而不是2.0,但meh,足够接近)

如果你使用逆变换,你可以将I1-4坐标转回C1-4,或者从屏幕坐标定位世界坐标等。

实现相机/视口有点棘手,如果只是在一开始,但它超出了什么被要求,所以我不会去那里(没有进一步的刺激)…

(Edit) 关于SDL…

SDL似乎不能很好地处理广义变换。我没有使用过它,但它的界面非常类似于GDI(窗口),我之前玩过一个游戏引擎,并遇到了这个问题(旋转+缩放纹理)。

有一个(看起来是非标准的)SDL函数,可以同时缩放和旋转纹理,但它的顺序是错误的,所以它总是保持图像的视角,这不是这里需要的。

基本几何将是好的,正如你所看到的,因为它的填充和线条不需要缩放,只需要定位。但是对于纹理…你将不得不编写代码一次渲染一个像素的纹理,或者使用变换(旋转后缩放),或分层(绘制一个alpha遮罩等距正方形并渲染一个预先计算的纹理)等组合…

当然,如果这是你的选择,使用一些适合原始几何和纹理数据,如OpenGL/Direct3D。我个人倾向于使用OpenGL/SFML。

不幸的是,我不能评论要求澄清,所以我必须回答一个问题:你不能转换所有四个点,然后从这些点计算从转换点的宽度和高度吗?

X=20, Y=10, Width=16, Height=16

如你所说

isometricX = cartX - cartY;
isometricY = (cartX + cartY) / 2;

isometricX1 = cartX1 - cartY1;
isometricY1 = (cartX1 + cartY1) / 2;

isometricWidth = std::abs(isometricY - isometricY1)

可能有更有效的路径但是因为我不懂笛卡尔几何我找不到解

EDITisometricWidth计算两点之间的距离,而不是宽度和高度另一个注意事项是,你需要对角(是的,我意识到另一个人可能是一个更好的答案:P)