Javascript 单击二维等轴测栅格中的检测?

Javascript 单击二维等轴测栅格中的检测?,javascript,click,2d,detection,isometric,Javascript,Click,2d,Detection,Isometric,我已经做了几年的网页开发工作,我慢慢地开始参与游戏开发,在我目前的项目中,我得到了这个等距图,我需要使用一个算法来检测哪个字段被点击。顺便说一下,这些都是在浏览器中使用Javascript实现的 地图 看起来,我添加了一些数字,向您显示字段(平铺)的结构及其ID。所有字段都有一个中心点(x,y的数组),绘制时四个角都基于该中心点。 正如你所看到的,这不是一个钻石形状,而是一个锯齿形的地图,没有角度(自上而下的视图),这就是为什么我自己找不到答案的原因,因为所有的文章和计算通常都是基于一个有角度的

我已经做了几年的网页开发工作,我慢慢地开始参与游戏开发,在我目前的项目中,我得到了这个等距图,我需要使用一个算法来检测哪个字段被点击。顺便说一下,这些都是在浏览器中使用Javascript实现的

地图
看起来,我添加了一些数字,向您显示字段(平铺)的结构及其ID。所有字段都有一个中心点(x,y的数组),绘制时四个角都基于该中心点。
正如你所看到的,这不是一个钻石形状,而是一个锯齿形的地图,没有角度(自上而下的视图),这就是为什么我自己找不到答案的原因,因为所有的文章和计算通常都是基于一个有角度的钻石形状

数字
这是一个动态地图,可以更改所有大小和数字以生成新地图。
我知道数据不多,但地图是根据地图和字段大小生成的。
-地图尺寸:x:800 y:400
-字段大小:80x80(角之间)
-所有字段的中心位置(x,y)

目标
提出一种算法,告诉客户端(游戏)在任何给定事件(点击、移动等)中鼠标位于哪个区域

免责声明
我确实想提到的是,我自己已经提出了一个可行的解决方案,但是我100%确信它可以用更好的方式编写(我的解决方案涉及很多嵌套的if语句和循环),这就是我在这里提问的原因

我的解决方案的一个例子是,我基本上找到一个角位于最近4个已知位置的正方形,然后根据两个最近字段之间的最小正方形得到结果。这有什么意义吗


询问我是否遗漏了什么。

我过去使用过的一种像素完美的命中检测方法(在OpenGL中,但概念也在这里)是对场景的屏幕外渲染,其中使用不同的颜色识别不同的对象

这种方法需要两倍的内存和两倍的渲染,但任意复杂场景的命中检测是通过简单的颜色查找完成的


由于您希望检测网格中的单元格,可能有更有效的解决方案,但我想提及这一解决方案,因为它简单灵活。

这一点以前已经解决过,让我参考我的笔记

以下是一些很好的资源:

让我知道这是否有帮助,祝你比赛好运

此代码计算给定不均匀间距的栅格中的位置。应该很快;几乎所有操作都是通过数学方法完成的,只使用一个循环。我稍后会考虑问题的另一部分

def cspot(x,y,length):
    l=length
    lp=length+1
    vlist = [ (l*(k%2))+(lp*((k+1)%2)) for k in range(1,y+1) ]
    vlist.append(1)
    return x + sum(vlist)

这是我想到的

function posInGrid(x, y, length) {
xFromColCenter = x % length - length / 2;
yFromRowCenter = y % length - length / 2;
col = (x - xFromColCenter) / length;
row = (y - yFromRowCenter) / length;
if (yFromRowCenter < xFromColCenter) {
    if (yFromRowCenter < (-xFromColCenter))--row;
    else++col;
} else if (yFromRowCenter > xFromColCenter) {
    if (yFromRowCenter < (-xFromColCenter))--col;
    else++row;
}
return "Col:"+col+", Row:"+row+", xFC:"+xFromColCenter+", yFC:"+yFromRowCenter;
}
函数posInGrid(x,y,长度){
xFromColCenter=x%长度-长度/2;
yFromRowCenter=y%长度-长度/2;
col=(x-xFromColCenter)/长度;
行=(y-yFromRowCenter)/长度;
if(yFromRowCenterxFromColCenter){
如果(yFromRowCenter<(-xFromColCenter))--col;
else++行;
}
返回“Col:+Col+”,行:+Row+”,xFC:+xFromColCenter+,yFC:+yFromRowCenter;
}
X和Y是图像中的坐标,长度是栅格的间距

现在它返回一个字符串,只是为了测试。。结果应该是行和列,这些是我选择的坐标:你的图块1有坐标(1,0),图块2是(3,0),图块10是(0,1),图块11是(2,1)。你可以把我的坐标转换成一行或两行的数字

和一个用于测试的JSFIDLE

干杯


EDIT:更改了return语句,保留了一些用于调试的变量。

等等。。。你是说图像中的图形角点彼此不相邻吗?@albert如果你是说所有的细胞是否都相互接触,那么是的,但是如果你问是否有更多的细胞在地图之外,那么就没有了。我发布的图像显示的是地图的精确大小,没有任何滚动。嗯,这是菱形地图的一个子集。你能用一个稀疏的数组来切角,或者其他你不打算用的东西吗?当然,还有网格坐标的45度旋转。问题是,我在任何点都不旋转。我有一个所有单元位置(中心点)的数组,基本上知道每个单元的大小。我的图片显示了细胞的形状,但它们实际上并不存在于游戏中,除了中心点之外也不使用。谢谢你的回答,但我可能应该提到这些细胞不是对象,也不是这样生成的。不过,我确实使用了一个缓冲区来检测游戏中正常对象的点击,但不是针对单元格,因为它们基本上不存在于游戏中(除了对象对齐),我不明白这是如何使这种方法无效的。如果网格是静态的,你可以有一个更多的缓冲区用于单元格命中检测——你只需要渲染缓冲区一次,问题不在于缓冲区。你的方法的问题是,游戏中根本没有细胞,除了其他不总是存在的对象的对齐。线(网格)基本上就是线,用来显示单元格。他们没有填写任何雪碧或颜色。如果你是这个意思的话,我需要在缓冲区中使用一个细胞形状的精灵/纹理吗?我希望有一个数学解决方案。正如我所说,可能有一个更有效的解决方案。但在这种情况下,一个数学解决方案只能更有效地利用内存,而不是简单的颜色查找。屏幕外缓冲区(与屏幕上缓冲区的分辨率相同)需要使用唯一的纯色渲染每个单元格,并且需要分别在这些颜色和单元格标识符之间进行映射。当您读取鼠标位置时