我正在开发等距游戏引擎,并且已经创建了像素完美点击检测算法。访问该项目,并注意单击检测能够检测到瓷砖的哪个边缘被单击。它还会检查y-index以单击最前面的图块。
我当前算法的解释:
等距网格由100 * 65px的图块图像组成。 TileW=100, TileL=50, tileH=15
该地图由三维数组表示map[z][y][x]。
瓦片中心点(x,y)的计算方式如下:
//x, y, z are the position of the tile
if(y%2===0) { x-=-0.5; } //To accommodate the offset found in even rows
this.centerX = (x*tileW) + (tileW/2);
this.centerY = (y*tileL) - y*((tileL)/2) + ((tileL)/2) + (tileH/2) - (z*tileH);
确定鼠标是否在图块上给定区域内的原型函数:
Tile.prototype.allContainsMouse = function() {
var dx = Math.abs(mouse.mapX-this.centerX),
dy = Math.abs(mouse.mapY-this.centerY);
if(dx>(tileW/2)) {return false;} //Refer to image
return (dx/(tileW*0.5) + (dy/(tileL*0.5)) < (1+tileHLRatio));
}
Tile.prototype.allContainsMouse()如果鼠标在绿色内,则返回true。通过检查dx>瓦片宽度的一半来裁切出红色区域
Tile.prototype.topContainsMouse = function() {
var topFaceCenterY = this.centerY - (tileH/2);
var dx = Math.abs(mouse.mapX-this.centerX),
dy = Math.abs(mouse.mapY-topFaceCenterY);
return ((dx/(tileW*0.5) + dy/(tileL*0.5) <= 1));
};
Tile.prototype.leftContainsMouse = function() {
var dx = mouse.mapX-this.centerX;
if(dx<0) { return true; } else { return false; }
};
(如果鼠标离开中心点)
Tile.prototype.rightContainsMouse = function() {
var dx = mouse.mapX-this.centerX;
if(dx>0) { return true; } else { return false; }
};
(如果鼠标在中心点的右边)
将所有方法合为一体:
遍历整个3d地图[z] [y] [x]数组
如果allContainsMouse()返回true,则map [z] [y] [x]是我们的鼠标所在的图块。
将此图块添加到数组tilesUnderneathMouse数组。
遍历tilesUnderneathMouse数组,然后选择最高的图块y。这是最前期的图块。
if(allContainsMouse && !topContainsMouse)
if(allContainsMouse && !topContainsMouse && leftContainsMouse)
(类似的概念适用于权利)
最后,我的问题:
#1您将如何做到这一点,以使其更有效(不遍历所有图块)(接受伪代码)
#2如果您无法回答#1,您有什么建议来提高点击检测的效率(已经考虑了大块加载)
我想到的是:
我最初试图通过不使用图块中心点来解决此问题,而是将mouse(x,y)位置直接转换为图块x,y。在我看来,这是最困难的代码,但也是最有效的解决方案。在正方形网格上,将(x,y)位置转换为网格上的正方形非常容易。但是,在交错的列网格中,您需要处理偏移量。我尝试使用带有x或y值的函数来计算偏移量,并返回结果偏移量y或x。arccos(cosx)的Zig-zag图解决了该问题。
使用这种方法检查鼠标是否在瓷砖内是很困难的,我无法弄清楚。我正在检查mouse(x,y)是否在y=mx+b取决于tileX,tileY近似值(近似正方形网格)的线下。
如果您到这里,谢谢!