很多研究已经证明,将网格点排列成六角网格的形式是一种最佳排列,在目前使用的四角网格显示器中,很容易出现锯齿,而六角因为在数学上和物理上的特性,理论上更适合作为座标系统。
比如一些更加讲究策略的游戏多就使用六角网格座标系统,如英雄无敌3,辐射,大航海时代,大菠萝1似乎也是。
这里要做的就是使用 GDI+ 绘制一个六角网格,网上关于这方面的资料很少。
实例图 :
计算采用六角网格的类直角逻辑坐标
/// <summary>
/// 生成指定大小的六角网格
/// </summary>
/// <param name="gridSize">六角格的大小(水平直径和垂直直径)</param>
/// <param name="mapSize">六角网格的大小</param>
/// <returns>六角网格的路径</returns>
public GraphicsPath BuildHexes(Size gridSize, Size mapSize)
{
List<PointF> lines = null ;
//六角格的水平半径和垂直半径
float wRad = (gridSize.Width / 2 );
float hRad = (gridSize.Height / 2 );
//六角格的水平垂直线,垂直线
float wLine = (float)(Math.Sqrt(Math.Pow(wRad, 2) - Math.Pow(wRad / 2, 2 )));
float hLine = (float)(Math.Sqrt(Math.Pow(hRad, 2) - Math.Pow(hRad / 2, 2 )));
//进行蜂窝式切合所必要的位移量
float wSpec = (wRad - wLine) * 2 ;
float hSpec = (hRad - hLine) * 2 ;
//六角格的中心点
float cx, cy;
GraphicsPath result = new GraphicsPath();
for (int y = 0; y < mapSize.Height; y++ )
{
for (int x = 0; x < mapSize.Width; x++ )
{
//计算当前六角格的中心点
cx = (gridSize.Width * (x + 1)) - wRad;
cy = (gridSize.Height * (y + 1)) - hRad;
cx = cx - (wSpec * x);
cy = cy - (hSpec * y) * 2 ;
if (y % 2 == 1 )
{
cx = cx + wLine;
}
//保存六角格的六个角的位置
lines = new List<PointF>(6 );
//北
PointF start = new PointF(cx, cy - hRad);
lines.Add(start);
//东北
lines.Add(new PointF(cx + wLine, cy - hRad / 2 ));
//东南
lines.Add(new PointF(cx + wLine, cy + hRad / 2 ));
//南
lines.Add(new PointF(cx, cy + hRad));
//西南
lines.Add(new PointF(cx - wLine, cy + hRad / 2 ));
//西北
lines.Add(new PointF(cx - wLine, cy - hRad / 2 ));
//回到起点:北
lines.Add(start);
result.AddLines(lines.ToArray());
result.CloseFigure();
}
}
return result;
}
/// 生成指定大小的六角网格
/// </summary>
/// <param name="gridSize">六角格的大小(水平直径和垂直直径)</param>
/// <param name="mapSize">六角网格的大小</param>
/// <returns>六角网格的路径</returns>
public GraphicsPath BuildHexes(Size gridSize, Size mapSize)
{
List<PointF> lines = null ;
//六角格的水平半径和垂直半径
float wRad = (gridSize.Width / 2 );
float hRad = (gridSize.Height / 2 );
//六角格的水平垂直线,垂直线
float wLine = (float)(Math.Sqrt(Math.Pow(wRad, 2) - Math.Pow(wRad / 2, 2 )));
float hLine = (float)(Math.Sqrt(Math.Pow(hRad, 2) - Math.Pow(hRad / 2, 2 )));
//进行蜂窝式切合所必要的位移量
float wSpec = (wRad - wLine) * 2 ;
float hSpec = (hRad - hLine) * 2 ;
//六角格的中心点
float cx, cy;
GraphicsPath result = new GraphicsPath();
for (int y = 0; y < mapSize.Height; y++ )
{
for (int x = 0; x < mapSize.Width; x++ )
{
//计算当前六角格的中心点
cx = (gridSize.Width * (x + 1)) - wRad;
cy = (gridSize.Height * (y + 1)) - hRad;
cx = cx - (wSpec * x);
cy = cy - (hSpec * y) * 2 ;
if (y % 2 == 1 )
{
cx = cx + wLine;
}
//保存六角格的六个角的位置
lines = new List<PointF>(6 );
//北
PointF start = new PointF(cx, cy - hRad);
lines.Add(start);
//东北
lines.Add(new PointF(cx + wLine, cy - hRad / 2 ));
//东南
lines.Add(new PointF(cx + wLine, cy + hRad / 2 ));
//南
lines.Add(new PointF(cx, cy + hRad));
//西南
lines.Add(new PointF(cx - wLine, cy + hRad / 2 ));
//西北
lines.Add(new PointF(cx - wLine, cy - hRad / 2 ));
//回到起点:北
lines.Add(start);
result.AddLines(lines.ToArray());
result.CloseFigure();
}
}
return result;
}
然后随便建一个 Form,覆写其 OnPaint 方法,如下:
protected override void
OnPaint(PaintEventArgs e)
{
base .OnPaint(e);
GraphicsPath path = BuildHexes(new Size(36, 20), new Size(10, 10 ));
e.Graphics.DrawPath(Pens.Blue, path);
}
{
base .OnPaint(e);
GraphicsPath path = BuildHexes(new Size(36, 20), new Size(10, 10 ));
e.Graphics.DrawPath(Pens.Blue, path);
}
这样你就能见到一个蜂窝状的六角网格了。
参考文献 :
六角网格上的图象算法及几何量定义
PS:
blog系统居然不允许链接中有来自 goo gle pag s.com 的内容/图片