在边界框内有效获取等距网格位置

Tri*_*tan 17 javascript math isometric

等距网格

我有一个等距网格系统,坐标从网格左上角的[0,0]开始(上图中显示的角落),x向图像底部递增,y向顶部递增(所以[ 0,height]将是顶角,[width,0]将是菱形的底角,宽度和高度是网格的大小,即200 x 200正方形)

无论如何我需要帮助的是获得一组等距网格位置,这些位置包含在图像中显示的蓝色框中.没有遍历每个x,y屏幕pos并获得相应的网格位置(请参阅我之前提到的关于如何从屏幕位置转换为网格位置的问题获取等距网格上的行/列.)我不知道如何有效地实现这一目标.

我之前发现的一个问题就是这里几乎完全相同的链接.答案是将网格渲染为每个网格方块的不同颜色的图像,然后检测广场下面的颜色,我已经实现了这个解决方案,但它很慢!我几乎在考虑检查选择框中每个像素的网格位置会更快.为什么哦为什么javascript循环这么慢!

我真的需要一个基于我的坐标系统来解决这个问题的数学解决方案,但我似乎无法想出一些有效的东西(并且处理选择框离开网格)

如果您需要更多信息,请与我们联系.

编辑:不幸的是,提供的答案到目前为止还没有工作,因为选择就像在正方形网格上有一个钻石选择区域,除非我错过了答案的点,否则实际上没有左上角,右下角要迭代?我已经优化了渲染方法,但是在大量选择中,它仍会在帧中添加明显的下降,因为它遍历所有像素检查颜色并获得相应的方块

ell*_*ben 10

线性代数就是答案.这里有两个感兴趣的坐标系:屏幕坐标和等距坐标.将所选区域的角从屏幕坐标转换为等距坐标将极大地帮助您.

设θ是等距坐标的x和y轴之间的角度,在屏幕上测量,单位是等距坐标中一步的像素长度.然后

var c = Math.cos(theta/2);
var s = Math.sin(theta/2);
var origin = [oX, oY]; //the pixel coordinates of (0, 0)
var unit = 20;
var iso2Screen = function(iso) {
  var screenX = origin[0] + unit * (iso[0] * c + iso[1] * c);
  var screenY = origin[1] + unit * (iso[0] * -s + iso[1] * s);
  return [screenX, screenY];
}
Run Code Online (Sandbox Code Playgroud)

我们得到了反转这种关系

var screen2Iso = function(screen) {
  var isoX = ((screen[0] - origin[0]) / c - (screen[1] - origin[1]) / s) / unit;
  var isoY = ((screen[0] - origin[0]) / c + (screen[1] - origin[1]) / s) / unit;
Run Code Online (Sandbox Code Playgroud)

现在将选择框每个角的屏幕坐标转换为等距坐标,并获得最小和最大x和y.

var cornersScreen = ...//4-element array of 2-element arrays
var cornersIso = [];
for(var i = 0; i < 4; i++) {
  cornersIso.push(screen2Iso(cornersScreen[i]));
}
var minX, maxX, minY, maxY;
minX = Math.min(cornersIso[0][0], cornersIso[1][0], cornersIso[2][0], cornersIso[3][0]);
maxX = Math.max(cornersIso[0][0], cornersIso[1][0], cornersIso[2][0], cornersIso[3][0]);
minY = Math.min(cornersIso[0][1], cornersIso[1][1], cornersIso[2][1], cornersIso[3][1]);
maxY = Math.max(cornersIso[0][1], cornersIso[1][1], cornersIso[2][1], cornersIso[3][1]);
Run Code Online (Sandbox Code Playgroud)

所有选定的等距点都位于等距框[minX,maxX] x [minY,maxY]内,但并非该框中的所有点都在选区内.

你可以做很多不同的事情来清除那个不在选择范围内的那些点; 我建议迭代等距x和y的整数值,将等距坐标转换为屏幕坐标,然后测试以查看该屏幕坐标是否位于选择框内,即:

var sMinX, sMaxX, sMinY, sMaxY;
sMinX = Math.min(cornersScreen[0][0], cornersScreen[1][0], cornersScreen[2][0], cornersScreen[3][0]);
sMaxX = Math.max(cornersScreen[0][0], cornersScreen[1][0], cornersScreen[2][0], cornersScreen[3][0]);
sMinY = Math.min(cornersScreen[0][1], cornersScreen[1][1], cornersScreen[2][1], cornersScreen[3][1]);
sMaxY = Math.max(cornersScreen[0][1], cornersScreen[1][1], cornersScreen[2][1], cornersScreen[3][1]);
var selectedPoints = [];
for(var x = Math.floor(minX); x <= Math.ceil(maxX); x++) {
  for(var y = Math.floor(minY); x <= Math.ceil(maxY); y++) {
    var iso = [x,y];
    var screen = iso2Screen(iso);
    if(screen[0] >= sMinX && screen[0] <= sMaxX && screen[1] >= sMinY && screen[1] <= sMaxY) {
      selectedPoints.push(iso);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*lek 7

我是学生为爱好做XNA游戏.我正在研究基于正方形的经典2D游戏(Project Squared).你的这个游戏让我想起了我的工作,所以我决定帮助你.

我认为应该使用数学,而不是你提到的图形.

首先,您应该知道哪个方格(网格上的位置)在"蓝框"(可能是选择框)的开头和选择结束时.所以现在你知道列表的开头和结尾了.

由于在您的游戏中,方块可能具有静态大小(或者您可以缩放相机,但从不增加宽度/高度),因此您可以轻松计算出选择框中的哪些方块.

现在,你知道你的方块是45°移动r/l.

(我说的是XNA,比如coordsys - 向左0,0)

If ( selectedStartSquare.selectionY <= square.height )
    startY = selectedStartSquare.selectionY
else startY = selectedStartSquare.selectionY + 1; 

if (selectedEndSquare.selectionY > square.height)
    endY = -||-.selectionY
else endY = -||- + 1;
Run Code Online (Sandbox Code Playgroud)

这将为您提供方块的起始和结束高度索引.您需要为X索引执行相同的操作.

现在,您拥有了获得所有方块所需的一切.通过selectedStartSquare.X中的X到endX和Y,从selectedStartSquare.Y到forY循环,但每次都改变start(startYIndex ++每个循环)

这只是一个很接近的例子,因为我从未使用等距游戏.这可能需要一些调整,但我"想!!" 这应该工作.(在睡觉之前写了这个,因为我已经在床上了,所以没有纸张...祝你好运)

对不起我的英语,我来自克罗地亚所以......