最近考虑开发一款兵棋软件,名字都想好了,叫犀牛兵棋,打算支持四边形地图和六边形地图。
前者比较好说,后者在根据屏幕坐标计算格子坐标的时候,稍微有点麻烦。
先说下我们的坐标系是x轴向右,y轴向上,原点在左下角。
格子地图坐标如下
根据格子坐标计算出对应世界坐标系的函数如下
QPointF GridCell6Manager::getWorldPosByCellCoordinate(int x,int y)
{
if (x % 2 == 0)
return QPointF(1.5f*res*(x+1),
(0.5*R3+R3*y)*res);
return QPointF(1.5f*res*(x + 1),
(R3 + y * R3)*res);
}
QPoint GridCell6Manager::getCellCoordinateByWorldPos(int x,int y)
{
QPoint point(-1,-1);
float xpos = x-res*0.5f;
float ypos = y/(R3*res) - 0.5f;
int yset[2] = {std::floorf(ypos),std::ceilf(ypos)};
xpos /= (1.5*World::getInstance().getWorldResolution());
int xset[2] = { std::floorf(xpos),std::ceilf(xpos)};
auto p00 = getWorldPosByCellCoordinate(xset[0],yset[0]);
auto p01 = getWorldPosByCellCoordinate(xset[0],yset[1]);
auto p10 = getWorldPosByCellCoordinate(xset[1],yset[0]);
auto p11 = getWorldPosByCellCoordinate(xset[1],yset[1]);
float d00 = distance2<float>(x,y,p00.x(),p00.y());
float d01 = distance2<float>(x,y,p01.x(),p01.y());
float d10 = distance2<float>(x,y,p10.x(),p10.y());
float d11 = distance2<float>(x,y,p11.x(),p11.y());
int i,j;
if(d00 < d01 && d00 < d10 && d00 < d11)
{
i = xset[0];
j = yset[0];
}
else if(d00 > d01 && d01 < d10 && d01 < d11)
{
i = xset[0];
j = yset[1];
}
else if(d10 < d00 && d10 < d01 && d10 < d11)
{
i = xset[1];
j = yset[0];
}
else
{
i = xset[1];
j = yset[1];
}
return QPoint(i,j);
}
其中res为格子边长,R3为sqrt(3)常量
在这个基础上就可以计算从世界坐标到格子坐标的转换了