很难将鼠标的位置转换为网格中图 block 的位置。当一切平坦时,数学看起来像这样:
this.position.x = Math.floor(((pos.y - 240) / 24) + ((pos.x - 320) / 48));
this.position.y = Math.floor(((pos.y - 240) / 24) - ((pos.x - 320) / 48));
其中 pos.x 和 pos.y 是鼠标的位置,240 和 320 是偏移量,24 和 48 是图 block 的大小。然后,位置包含我悬停在其上的图 block 的网格坐标。这在平坦的表面上效果相当好。
现在我要添加高度,但数学并未考虑这一点。
该网格是一个包含噪声的 2D 网格,它被转换为高度和图 block 类型。高度实际上只是对图 block “Y”位置的调整,因此两个图 block 可以绘制在同一位置。
我不知道如何确定我将鼠标悬停在哪个图 block 上。
编辑:
取得了一些进展...之前,我依靠鼠标悬停事件来计算网格位置。我只是更改了它以在绘制循环本身中进行计算,并检查坐标是否在当前正在绘制的图 block 的限制内。虽然会产生一些开销,但不确定我是否对此非常满意,但我会确认它是否有效。
编辑 2018 年:
我没有答案,但由于这是一个开放的赏金,请自行获取一些code and a demo
网格本身被简化;
let grid = [[10,15],[12,23]];
这会导致这样的绘图:
for (var i = 0; i < grid.length; i++) {
for (var j = 0; j < grid[0].length; j++) {
let x = (j - i) * resourceWidth;
let y = ((i + j) * resourceHeight) + (grid[i][j] * -resourceHeight);
// the "+" bit is the adjustment for height according to perlin noise values
}
}
编辑赏金后:
参见 GIF。接受的答案有效。延迟是我的错,屏幕在鼠标移动时还没有更新,而且帧速率很低。很明显,它带回了正确的瓷砖。
最佳答案
有趣的任务。
让我们尝试简化它 - 让我们解决这个具体案例
解决方案
工作版本在这里:https://github.com/amuzalevskiy/perlin-landscape (更改https://github.com/jorgt/perlin-landscape/pull/1)
说明
首先想到的是:
只需两步:
- 找到与某些图 block 组匹配的垂直列
- 从下到上迭代集合中的图 block ,检查光标是否低于顶线
第 1 步
这里我们需要两个函数:
检测列:
function getColumn(mouseX, firstTileXShiftAtScreen, columnWidth) {
return (mouseX - firstTileXShiftAtScreen) / columnWidth;
}
提取与此列对应的图 block 数组的函数。
将图像旋转 45 度。红色数字是columnNo。 3 列突出显示。 X轴是水平的
function tileExists(x, y, width, height) {
return x >= 0 & y >= 0 & x < width & y < height;
}
function getTilesInColumn(columnNo, width, height) {
let startTileX = 0, startTileY = 0;
let xShift = true;
for (let i = 0; i < columnNo; i++) {
if (tileExists(startTileX + 1, startTileY, width, height)) {
startTileX++;
} else {
if (xShift) {
xShift = false;
} else {
startTileY++;
}
}
}
let tilesInColumn = [];
while(tileExists(startTileX, startTileY, width, height)) {
tilesInColumn.push({x: startTileX, y: startTileY, isLeft: xShift});
if (xShift) {
startTileX--;
} else {
startTileY++;
}
xShift = !xShift;
}
return tilesInColumn;
}
第 2 步
要检查的图 block 列表已准备就绪。现在,对于每个图 block ,我们需要找到一条顶线。我们还有两种类型的图 block :左图和右图。我们已经在构建匹配图 block 集期间存储了此信息。
function getTileYIncrementByTileZ(tileZ) {
// implement here
return 0;
}
function findExactTile(mouseX, mouseY, tilesInColumn, tiles2d,
firstTileXShiftAtScreen, firstTileYShiftAtScreenAt0Height,
tileWidth, tileHeight) {
// we built a set of tiles where bottom ones come first
// iterate tiles from bottom to top
for(var i = 0; i < tilesInColumn; i++) {
let tileInfo = tilesInColumn[i];
let lineAB = findABForTopLineOfTile(tileInfo.x, tileInfo.y, tiles2d[tileInfo.x][tileInfo.y],
tileInfo.isLeft, tileWidth, tileHeight);
if ((mouseY - firstTileYShiftAtScreenAt0Height) >
(mouseX - firstTileXShiftAtScreen)*lineAB.a + lineAB.b) {
// WOHOO !!!
return tileInfo;
}
}
}
function findABForTopLineOfTile(tileX, tileY, tileZ, isLeftTopLine, tileWidth, tileHeight) {
// find a top line ~~~ a,b
// y = a * x + b;
let a = tileWidth / tileHeight;
if (isLeftTopLine) {
a = -a;
}
let b = isLeftTopLine ?
tileY * 2 * tileHeight :
- (tileX + 1) * 2 * tileHeight;
b -= getTileYIncrementByTileZ(tileZ);
return {a: a, b: b};
}
关于javascript - 鼠标位置到等距图 block (包括高度),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21842814/