1、外观
在开始讲解之前,先上图!
一个传统的四方格地图。
一个倾斜X轴的六角格地图。
一个水平X轴的六角格地图。
2、六角网格的寻址
Cell坐标系(CellMap)
六角网格的方向
建立Map坐标系
我们平时使用的坐标,要么是屏幕坐标(2D游戏),要么是笛卡尔坐标(3D游戏)。
上述两种坐标系最大的特点是:
1、坐标轴互相垂直。
2、坐标值连续。
根据第一节的直观观察,可以知道六角格无法建立出垂直的坐标轴。
而为了满足第二点,一般都为其建立斜X轴坐标系,或不太水平的坐标系。
寻址网格 (AddressingGrid)
过所有Cell的中点做水平和垂直方向上的线,这些互相垂直/平行的线形成的网格,称为六角网格的寻址网格。
寻址网格的责任是将worldPosition 转化为 GridPosition ,再通过GridPosition转化为CellPosition。如下图所示:
可以看到,一个GridCell为一个正方形,规定六角形边长为 SideLength , 则这个GridCell的边长为 3/2 * SideLength;
同时,我们也认为一个HexCell的Size 和 GridCell的Size等值。
通过上图可以看到,这个Grid的左上角并不在worldspace 的(0,0)位置,而是在 (-0.5*cellsize.x , -0.5*cellsize.y )的地方。
看到上图彩色的部分了吗?整个CellMap 会被GridCell 分割成A、B两种情况,我们需要关注的是gridCell框住的三个HexCell中处于右下角的那个。
对于情况A,就是绿色部分, 对于情况B,就是粉色部分。稍后在描述 GridPosition to CellPosition 的时候会用到。
世界坐标和六角网格坐标之间的关系 (CellPosition To WorldPosition)
这是一个 BiasHexMap ,可以看到, cell.y = 0 的格子在WorldSpace 上,一直在往下走。因此当一个CellPosition -> WorldPosition 时,需要考虑其cell.x的值对world.y的影响。我们再看一张 HorizontalHexMap 的图。
可以看到,HorizontalHexMap 只有偶数列才会不一样,奇数列和没有发生什么特别的事情。
前面我们知道 CellSize = 3/2*SideLength;
因此 cell的左上角的(上图左上角的蓝色框框的LeftTop点)
world.x = cell.x * cellsize.x
world.y = cell.y * cellsize.y + cell.x * cellsize.y * 0.5
cellCenter.x = world.x + SideLength
cellCenter.y = world.y + SideLength * sqrt(3);
世界坐标和寻址网格坐标的关系(WorldPosition To GridPosition)
寻址网格坐标和六角网格坐标的关系( GridPosition To CellPosition)
选取正确的Cell (Pick Cell In Grid)
为了选择出正确的Cell,只需要在WorldSpace下计算 Point到哪个中点的距离近就可以了。
因此可以简单的判断Cell :
d = Min( d0, Min(d1,d2));
然后就可以得知是哪个Cell了。
推导过程如下:
My PickCell Method
Cell Adjacent
而且 HorizontalHexCell 还要区分奇偶列。
public static class Adjacent
{
public static class Quad
{
/*
* lefttop(0) top(1) righttop(2);
* left(7) self(-1) right(3);
* leftbottom(6) bottom(5) rightbottom(4);
*/
public static readonly Position Top = new Position(0, -1);
public static readonly Position Left = new Position(-1, 0);
public static readonly Position Bottom = new Position(0, 1); //- Top;
public static readonly Position Right = new Position(1, 0); //- Left;
public static readonly Position LeftTop = new Position(-1, -1);//Left + Top;
public static readonly Position LeftBottom = new Position(-1, 1);//Left + Bottom;
public static readonly Position RightTop = new Position(1, -1);//Right + Top;
public static readonly Position RightBottom = new Position(1, 1);//Right + Bottom;
}
public static class BiasHex
{
/* 倾斜坐标轴,采用 lefttop -> rightbottom为x, top->bottom 为y;
* 仔细体会下;
* top(1:[0,-1]);
* lefttop(0:[-1,0]) righttop(2:[1,-1]);
* self(-1:[0,0]);
* leftbottom(5:[-1,1]) rightbottom(3:[1,0]);
* bottom(4:[0,1]);
*/
public static readonly Position Top = new Position(0, -1);
public static readonly Position Bottom = new Position(0, 1);//-Top;
public static readonly Position LeftTop = new Position(-1, 0);
public static readonly Position LeftBottom = new Position(-1, 1);// + LeftTop + Bottom;
public static readonly Position RightTop = new Position(1, -1); //- LeftBottom;
public static readonly Position RightBottom = new Position(1, 0);// - LeftTop;
}
public static class HorizontalHex
{
/* 水平坐标轴;
* top->bottom 为y;
* 偶数列采用 leftbotoom -> self - > rightbottom为x; __0__
* / \
* 0 0
* 奇数列采用 leftup -> self - > rightup为x; 0 0
* \__0__/
* 仔细体会下;
*/
public static class Even
{
/*
* top(1:[0,-1]);
* lefttop(0:[-1,-1]) righttop(2:[1,-1]);
* self(-1:[0,0]);
* leftbottom(5:[-1,0]) rightbottom(3:[1,0]);
* bottom(4:[0,1]);
*/
public static readonly Position Top = new Position(0, -1);
public static readonly Position Bottom = new Position(0, 1);//-Top;
public static readonly Position LeftTop = new Position(-1, -1);
public static readonly Position LeftBottom = new Position(-1, 0);// + LeftTop + Bottom;
public static readonly Position RightTop = new Position(1, -1); //- LeftBottom;
public static readonly Position RightBottom = new Position(1, 0);// - LeftTop;
}
public static class Uneven
{
/*
* top(1:[0,-1]);
* lefttop(0:[-1,0]) righttop(2:[1,0]);
* self(-1:[0,0]);
* leftbottom(5:[-1,1]) rightbottom(3:[1,1]);
* bottom(4:[0,1]);
*/
public static readonly Position Top = new Position(0, -1);
public static readonly Position Bottom = new Position(0, 1);//-Top;
public static readonly Position LeftTop = new Position(-1, 0);
public static readonly Position LeftBottom = new Position(-1, 1);// + LeftTop + Bottom;
public static readonly Position RightTop = new Position(1, 0); //- LeftBottom;
public static readonly Position RightBottom = new Position(1, 1);// - LeftTop;
}
}
}
CellPosition - > WorldPosition