.net 在六角网格中捕捉到最近的六角中心
我正在尝试创建一个基于网格的游戏。到目前为止,我有一个基于六边形瓷砖的网格,其坐标方案如下所示:.net 在六角网格中捕捉到最近的六角中心,.net,algorithm,c++-cli,rounding,hexagonal-tiles,.net,Algorithm,C++ Cli,Rounding,Hexagonal Tiles,我正在尝试创建一个基于网格的游戏。到目前为止,我有一个基于六边形瓷砖的网格,其坐标方案如下所示: col 0 | col 1 | | col 2 | | | __ | __ __ __ __ /00\__/02\__/04\__/06\__/08\__ \__/01\__/03\__/05\__/07\__/09\--- row 0 /10\__/12\__/14\__/16\__/18\__/ \__/11\__/13\__/15\__/17\__/
col 0
| col 1
| | col 2
| | |
__ | __ __ __ __
/00\__/02\__/04\__/06\__/08\__
\__/01\__/03\__/05\__/07\__/09\--- row 0
/10\__/12\__/14\__/16\__/18\__/
\__/11\__/13\__/15\__/17\__/19\--- row 1
/20\__/22\__/24\__/26\__/28\__/
\__/21\__/23\__/25\__/27\__/29\--- row 2
/30\__/32\__/34\__/36\__/38\__/
\__/ \__/ \__/ \__/ \__/ --- row 3
在现实生活中,每个六边形的颜色都是随机的:
我想弄清楚的是,当用户点击一个六边形时,我如何确定他们点击了哪个六边形
到目前为止,我尝试的代码如下:
private: System::Void MyForm_MouseDown(System::Object^ sender,
System::Windows::Forms::MouseEventArgs^ e) {
int CloseI=0,CloseJ=0;
CloseJ = FindNearesetX(e->X);
CloseI = FindNearesetY(e->Y);
//Grid[down(y)][along(x)]
P1.X = Grid[CloseI][CloseJ].GetX();
P1.Y = Grid[CloseI][CloseJ].GetY();
} // END MOUSE DOWN EVENT
int FindNearesetX(int ActualX){
int ClosestJPos;
ClosestJPos = ((ActualX-Grid[0][0].GetX())/(1.5*HexSideLength));
return ClosestJPos;
}//END FIND NEAREST X
int FindNearesetY(int ActualY){
int ClosestIPos;
ClosestIPos = ((ActualY-Grid[0][0].getY())/(HexHeight));
return ClosestIPos;
}//END FIND NEAREST Y
private: System::Void MyForm_MouseMove(System::Object^ sender,
System::Windows::Forms::MouseEventArgs^ e) {
this->Invalidate();
P2.X = e->X;
P2.Y = e->Y;
} // END MOUSE MOVE EVENT
然而,这并没有达到我的预期效果,这是因为当用户单击六边形中心点的左侧时,它会捕捉到他们单击的六边形左侧的六边形,并且如果他们单击所有奇数列上的中心点上方,它会捕捉到他们单击的六边形上方的六边形
我已经在这个问题上纠缠了两天了,我真的很想把它弄清楚。
感谢单击的点将始终最接近发生单击的六边形的中心,除非该点正好位于两个六边形之间,在这种情况下,它将与两个中心等距。两点之间距离的方程式为SQRT((x1-x2)^2+(y1-y2)^2)
您不必测试到每个六边形的距离。通过创建x/y阈值,可以将测试限制在附近的六边形。例如,如果六边形的宽度为10,且点位于(51,73),则不必测试x坐标小于40或大于70的六边形。实际上,由于六边形的规则形状(所有边的长度相同),这就像在六角形瓷砖列表中循环一样简单,只需单击鼠标即可确定哪个瓷砖的中心距离最近 C++伪代码:
//assuming "map" is an array of "Tile" pointers
Tile *closest = nullptr;
int fromClosestCenterToClick = INT_MAX;
for (int row = 0; row < map.numRows(); row++)
{
for (int col = 0; col < map.numCols(); col++)
{
int distance = std::sqrt(std::pow(map[row][column]->center.x - mouseClickX, 2) + std::pow(map[row][column]->center.y - mouseClickY, 2) < fromClosestCenterToClick);
if (distance < fromClosestCenterToClick)
{
closest = map[row][column];
fromClosestCenterToClick = distance;
}
}
}
//closest now holds the correct tile
//假设“map”是一个“Tile”指针数组
瓦片*最近=空PTR;
int fromClosestCenterToClick=int_MAX;
对于(int row=0;rowcenter.x-mouseClickX,2)+std::pow(map[row][column]->center.y-mouseClickY,2)
一个人应该能够找到最接近O(1)复杂度的六边形:
odd even odd even
0 +----+ | | +----+ |
| 00 |\ | | | 02 | |
| | \+----+ | | +
| | /| 01 | | | |
H +----+/ | | +----+ |
| 10 |\ | | | 12 | |
| | \+----+ | | +
| | /| 11 | | | |
2H +----+/ | | +----+ |
0....X..W.......2W......3W
角“+”也是六边形的角当‘x’mod W
SS2DCoordinates coordinatesForHexAtPoint(float a, float b)
{
// Get basic hex information - pseudocode
float radius = <radius of one hexagon>
// Estimate the most likely hex and round to nearest values
float x = 2.0/3.0*a/radius;
float z = (1.0/3.0*sqrt(3.0)*b-1.0/3.0*a)/radius;
float y = -x-z;
int ix = (int)round((floor(x-y)-floor(z-x))/3.0);
int iy = (int)round((floor(y-z)-floor(x-y))/3.0);
int iz = (int)round((floor(z-x)-floor(y-z))/3.0);
// Adjust to flat coordinates on the offset numbering system
SS2DCoordinates corrected = hexToFlatCoordinates(SS3DCoordinatesMake(ix, iy, iz));
corrected.x --;
return axialToOffsetCoordinates(corrected);
}
SS2DCoordinates hexToFlatCoordinates(SS3DCoordinates hex)
{
SS2DCoordinates coordinates;
coordinates.x = hex.x;
coordinates.y = hex.z;
return coordinates;
}
SS2DCoordinates axialToOffsetCoordinates(SS2DCoordinates axial)
{
SS2DCoordinates offset;
offset.x = axial.x;
offset.y = axial.y + (NSInteger)ceilf((float)axial.x/2.0);
return offset;
}
ss2d六点坐标(浮点a、浮点b)
{
//获取基本十六进制信息-伪代码
浮动半径=
//估计最可能的十六进制和四舍五入到最接近的值
浮动x=2.0/3.0*a/半径;
浮动z=(1.0/3.0*sqrt(3.0)*b-1.0/3.0*a)/半径;
浮动y=-x-z;
int ix=(int)圆形((地板(x-y)-地板(z-x))/3.0);
int iy=(int)圆形((地板(y-z)-地板(x-y))/3.0);
int iz=(int)圆形((地板(z-x)-地板(y-z))/3.0);
//调整到偏移编号系统上的平面坐标
校正的SS2D坐标=六角坐标(SS3DCoordinateMake(ix,iy,iz));
更正.x--;
返回轴向偏移设置坐标(校正);
}
SS2D坐标六角坐标平面坐标(SS3D坐标六角)
{
ss2d坐标;
坐标x=十六进制x;
坐标y=十六进制z;
返回坐标;
}
SS2D坐标轴偏移设置坐标(SS2D坐标轴)
{
ss2d坐标偏移;
偏移量x=轴向偏移量x;
偏移量y=轴向y+(NSInteger)ceilf((浮动)轴向x/2.0);
返回偏移量;
}
gah,你复制了我的answer@TylerDurdenxD我可能先开始打字,但是是的。讽刺的是,你的更完整。阈值是个好主意+1此外,由于您只对查找最近的六边形感兴趣,您应该能够省略平方根检查,因为实际长度不会用于任何东西。如果要检查大量多边形,这可能会节省一些周期。泰勒基于宽度的剔除点也是一个非常快的优化,你应该考虑实现,并且绝对应该被用作一个预测试。在一个实际的实现中,你不需要做sqrt,只需要差分的平方和,即点之间的方差。我发布这个问题已经2年了,但我确实记得看到过那个帖子,我相信它并没有解决我的问题(尽管我确信它有帮助),然而,对于我来说,它太长了,我记不起它为什么没有回答我的问题的细节。这么长时间之后,在这篇文章上看到活动真奇怪!啊哈