Javascript 将屏幕坐标转换为等轴测地图坐标

Javascript 将屏幕坐标转换为等轴测地图坐标,javascript,math,game-engine,pixi.js,Javascript,Math,Game Engine,Pixi.js,我正在使用菱形图案生成等距平铺贴图: tileWidth = 128; tileHeight = 94; for (var x = 0; x < rows; x++) { for (var y = 0; y < cols; y++) { var screenX = (x - y) * tileWidthHalf; var screenY = (x + y) * tileHeightHalf; drawTile(screenX, screenY); }

我正在使用菱形图案生成等距平铺贴图:

tileWidth = 128;
tileHeight = 94;

for (var x = 0; x < rows; x++) {
  for (var y = 0; y < cols; y++) {
    var screenX = (x - y) * tileWidthHalf;
    var screenY = (x + y) * tileHeightHalf;
    drawTile(screenX, screenY);
  }
}
对于
0,0
平铺,它可以正常工作,但之后无法生成正确的值


我只是无法想出正确的数学方法——我是遗漏了一些琐碎的东西,还是整个过程都错了?

我不知道你是如何想出这个解决方案的。你必须解方程组,方程组给出以下解:

x = 0.5 * ( screenX / tileWidthHalf + screenY / tileHeightHalf)
y = 0.5 * (-screenX / tileWidthHalf + screenY / tileHeightHalf)
如果需要瓷砖索引,请使用代码中的
floor


我只能猜测坐标系中瓷砖的对齐方式。但是从您在评论中发布的屏幕截图来看,我假设您需要将
screenX
(screenX-tileWidthHalf)
进行交换,以获得准确的值。

我正在为您的
tileWidth
编写
w
,为
tilewhight
编写
h
。使用这种表示法,基本上

screenX = (x - y)*(w/2) = (w/2)*x + (-w/2)*y
screenY = (x + y)*(h/2) = (h/2)*x + (h/2)*y
这是一个线性变换,你也可以用矩阵表示法这样写:

⎛x⎞ ↦ ⎛w/2 -w/2⎞ ⎛x⎞
⎝y⎠   ⎝h/2  h/2⎠ ⎝y⎠
要反转此操作,需要将其反转。对于2×2矩阵的逆,存在一个矩阵。交换左上角和右下角的条目。否定另外两个。用行列式除以一切。使用它,您就可以进行逆变换:

⎛x⎞ ↦ 2/ ⎛ h/2 w/2⎞ ⎛x⎞ = ⎛ 1/w 1/h⎞ ⎛x⎞
⎝y⎠   wh ⎝-h/2 w/2⎠ ⎝y⎠   ⎝-1/w 1/h⎠ ⎝y⎠
所以在你的符号中,你得到

x = screenY / tileHeight + screenX / tileWidth
y = screenY / tileHeight - screenX / tileWidth

这也是尼科写的。将非整数坐标转换回整数取决于放置每个磁贴的参考点的位置。

Simple是一个相对术语,我需要花一点时间来理解它。@MvG你能解释一下你是如何找到转换矩阵的吗?@DRz我已经扩展了我的答案,使这一步更清楚。我也尝试过这个方法,但它似乎为每个磁贴的左右两侧产生了不同的值。我想知道这种差异是否来自于精灵的锚定点是左上角,而不是中间?我已经为瓷砖贴上标签,以便于调试,但更改锚定点没有任何帮助。-磁贴0,0的左半部分报告为-1,0,右半部分正确。平铺
1,0
的左半部分报告为
-1,1
,中间部分报告为
1,0
,右侧报告为
1,2
。不知为什么,除非您使用非标准坐标系,否则此图像与公式不匹配。代码表明原点位于左角,x轴指向右上角,y轴指向右下角。你有没有试过舍入,看看你得到了什么值?我假设平铺是沿两个轴的正方向绘制的。我更新了新代码的解决方案。啊,我刚刚从博客文章中看到这正是解决方案。如果这仅适用于部分瓷砖,则这是一个轴和圆的问题。但既然你没有写过这方面的任何东西,我就不能告诉你可能有什么问题。这是因为你的图纸和坐标系不匹配。您只需记住,互动程序的位置实际上并不在互动程序中。未来访客:Nico的解决方案(公认的解决方案)是互联网上众多不同解决方案中唯一适合我的解决方案。我在看这篇文章-你必须用(screenX-tileWidthHalf)代替screenX,正如Nico在回答中所建议的那样。请参见Nico回答中的我的评论。一定要确定结果。Nico的解决方案是正确的,但请记住必须对screenx、screeny、tileWidthHalf和tileHeightHalf使用浮动,否则精度不够。我正在使用ints,但它不能正常工作。将这些更改为浮动,它可以完美地工作。
x = screenY / tileHeight + screenX / tileWidth
y = screenY / tileHeight - screenX / tileWidth