二维等距网格中的点击检测?

发布于 2024-10-31 20:16:58 字数 878 浏览 9 评论 0原文

我从事网络开发已经很多年了,我正在慢慢地参与游戏开发,对于我当前的项目,我有这个等轴测图,我需要使用算法来检测正在单击哪个字段。顺便说一句,这一切都是在浏览器中使用 Javascript 实现的。

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

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

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

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

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

问我是否错过了什么。

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.

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.

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)

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.

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?

Ask if I missed something.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风蛊 2024-11-07 20:16:58

这就是我想到的,

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和Y是图像中的坐标,长度是网格的间距。

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

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

干杯。

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

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.

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.

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

Cheers.

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

久隐师 2024-11-07 20:16:58

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

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

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

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.

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.

葵雨 2024-11-07 20:16:58

这个问题之前已经解决了,让我查阅我的笔记...

这里有一些很好的资源:

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

此处发布的线程中有用的文章,用 Java

让我知道这是否有帮助,祝您游戏顺利!

该代码计算给定不均匀间距的网格中的位置。应该相当快;几乎所有运算都是通过数学方式完成的,仅使用一个循环。稍后我会思考问题的另一部分。

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)

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

Useful article in the thread posted here, in 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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文