在2D等距网格中单击检测?

时间:2022-11-21 20:11:19

I've been doing web development for years now and I'm slowly getting myself involved with game development and for my current project I've got this isometric map, where I need to use an algorithm to detect which field is being clicked on. This is all in the browser with Javascript by the way.

我已经进行了多年的网络开发,而且我正慢慢地参与游戏开发,对于我目前的项目,我已经有了这个等距地图,我需要使用算法来检测哪个字段被点击。这是所有在浏览器中使用Javascript的方式。

The map
It looks like this and I've added some numbers to show you the structure of the fields (tiles) and their IDs. All the fields have a center point (array of x,y) which the four corners are based on when drawn.
As you can see it's not a diamond shape, but a zig-zag map and there's no angle (top-down view) which is why I can't find an answer myself considering that all articles and calculations are usually based on a diamond shape with an angle.

地图它看起来像这样,我添加了一些数字来显示字段(图块)的结构及其ID。所有字段都有一个中心点(x,y数组),四个角在绘制时基于这些中心点。你可以看到它不是钻石形状,而是一个曲折的地图,没有角度(自上而下的视图)这就是为什么我自己无法找到答案,因为所有的文章和计算通常都是基于钻石形状有一个角度。

The numbers
It's a dynamic map and all sizes and numbers can be changed to generate a new map.
I know it isn't a lot of data, but the map is generated based on the map and field sizes.
- Map Size: x:800 y:400
- Field Size: 80x80 (between corners)
- Center position of all the fields (x,y)

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

The goal
To come up with an algorithm which tells the client (game) which field the mouse is located in at any given event (click, movement etc).

目标提出一种算法,告诉客户端(游戏)鼠标位于任何给定事件(点击,移动等)的哪个字段。

Disclaimer
I do want to mention that I've already come up with a working solution myself, however I'm 100% certain it could be written in a better way (my solution involves a lot of nested if-statements and loops), and that's why I'm asking here.

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

Here's an example of my solution where I basically find a square with corners in the nearest 4 known positions and then I get my result based on the smallest square between the 2 nearest fields. Does that make any sense?

这是我的解决方案的一个例子,我基本上找到一个在最近的4个已知位置有角的正方形,然后根据2个最近的场之间的最小平方得到我的结果。这有任何意义吗?

Ask if I missed something.

问我是否错过了什么。

3 个解决方案

#1


2  

Here's what I came up with,

这是我想出来的,

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

X and Y are the coords in the image, and length is the spacing of the grid.

X和Y是图像中的坐标,长度是网格的间距。

Right now it returns a string, just for testing.. result should be row and col, and those are the coordinates I chose: your tile 1 has coords (1,0) tile 2 is(3,0), tile 10 is (0,1), tile 11 is (2,1). You could convert my coordinates to your numbered tiles in a line or two.

现在它返回一个字符串,仅用于测试..结果应该是row和col,那些是我选择的坐标:你的瓷砖1有坐标(1,0)瓷砖2是(3,0),瓷砖10是( 0,1),图块11是(2,1)。您可以将我的坐标转换为一行或两行中的编号图块。

And a JSFiddle for testing http://jsfiddle.net/NHV3y/

和一个用于测试的JSFiddle http://jsfiddle.net/NHV3y/

Cheers.

干杯。

EDIT: changed the return statement, had some variables I used for debugging left in.

编辑:更改了返回语句,有一些我用于调试的变量。

#2


0  

A pixel perfect way of hit detection I've used in the past (in OpenGL, but the concept stands here too) is an off screen rendering of the scene where the different objects are identified with different colors.

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

This approach requires double the memory and double the rendering but the hit detection of arbitrarily complex scenes is done with a simple color lookup.

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

Since you want to detect a cell in a grid there are probably more efficient solutions but I wanted to mention this one for it's simplicity and flexibility.

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

#3


0  

This has been solved before, let me consult my notes...

这已经解决了,让我来看看我的笔记......

Here's a couple of good resources:

这里有几个很好的资源:

From Laserbrain Studios, The basics of isometric programming

来自Laserbrain Studios,等距编程的基础知识

Useful article in the thread posted here, in Java

在这里发布的线程中有用的文章,用Java

Let me know if this helps, and good luck with your game!

如果这有帮助,请告诉我,祝你的游戏好运!

This code calculates the position in the grid given the uneven spacing. Should be pretty fast; almost all operations are done mathematically, using just one loop. I'll ponder the other part of the problem later.

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

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)

#1


2  

Here's what I came up with,

这是我想出来的,

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

X and Y are the coords in the image, and length is the spacing of the grid.

X和Y是图像中的坐标,长度是网格的间距。

Right now it returns a string, just for testing.. result should be row and col, and those are the coordinates I chose: your tile 1 has coords (1,0) tile 2 is(3,0), tile 10 is (0,1), tile 11 is (2,1). You could convert my coordinates to your numbered tiles in a line or two.

现在它返回一个字符串,仅用于测试..结果应该是row和col,那些是我选择的坐标:你的瓷砖1有坐标(1,0)瓷砖2是(3,0),瓷砖10是( 0,1),图块11是(2,1)。您可以将我的坐标转换为一行或两行中的编号图块。

And a JSFiddle for testing http://jsfiddle.net/NHV3y/

和一个用于测试的JSFiddle http://jsfiddle.net/NHV3y/

Cheers.

干杯。

EDIT: changed the return statement, had some variables I used for debugging left in.

编辑:更改了返回语句,有一些我用于调试的变量。

#2


0  

A pixel perfect way of hit detection I've used in the past (in OpenGL, but the concept stands here too) is an off screen rendering of the scene where the different objects are identified with different colors.

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

This approach requires double the memory and double the rendering but the hit detection of arbitrarily complex scenes is done with a simple color lookup.

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

Since you want to detect a cell in a grid there are probably more efficient solutions but I wanted to mention this one for it's simplicity and flexibility.

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

#3


0  

This has been solved before, let me consult my notes...

这已经解决了,让我来看看我的笔记......

Here's a couple of good resources:

这里有几个很好的资源:

From Laserbrain Studios, The basics of isometric programming

来自Laserbrain Studios,等距编程的基础知识

Useful article in the thread posted here, in Java

在这里发布的线程中有用的文章,用Java

Let me know if this helps, and good luck with your game!

如果这有帮助,请告诉我,祝你的游戏好运!

This code calculates the position in the grid given the uneven spacing. Should be pretty fast; almost all operations are done mathematically, using just one loop. I'll ponder the other part of the problem later.

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

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)