最近考慮開發(fā)一款兵棋軟件,名字都想好了,叫犀牛兵棋,打算支持四邊形地圖和六邊形地圖。
前者比較好說,后者在根據(jù)屏幕坐標(biāo)計(jì)算格子坐標(biāo)的時(shí)候,稍微有點(diǎn)麻煩。
先說下我們的坐標(biāo)系是x軸向右,y軸向上,原點(diǎn)在左下角。
格子地圖坐標(biāo)如下

根據(jù)格子坐標(biāo)計(jì)算出對應(yīng)世界坐標(biāo)系的函數(shù)如下
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)常量
在這個(gè)基礎(chǔ)上就可以計(jì)算從世界坐標(biāo)到格子坐標(biāo)的轉(zhuǎn)換了