Click detection in a 2D isometric grid?

﹥>﹥吖頭↗ 提交于 2020-01-02 08:36:58

问题


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.


回答1:


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.




回答2:


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.




回答3:


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)


来源:https://stackoverflow.com/questions/5611982/click-detection-in-a-2d-isometric-grid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!