SLG游戏中绘制六边形网格地形

 

本文章主要工作是六边形网格的绘制,可以用来制作地图功能。

 

先来看一下这样的图:

 

如图所示。六边形有6个方向,6个顶点,同时定义中心点到边的最短距离为内径innerRadius,定义中心点到顶点的距离为外径outerRadius。

六边形可以拆分为6个等边三角形,所以很容易得出:
 


定义游戏中六边形的边长(即外径)为1

 

HexMetrics类代码实现:

public static class HexMetrics

{

    /// <summary>

    /// 外径,中心到顶点距离

    /// </summary>

    public const float outerRadius = 10f;

    /// <summary>

    /// 内径,中心到边距离,0.866025404为二分之根号三的近似值

    /// </summary>
    //Mathf.Sin(60) = 0.866025404;
    public const float innerRadius = outerRadius * 0.866025404f;

    /// <summary>

    /// 六边形的六个顶点坐标

    /// </summary>

    public static readonly Vector3[] corners = {

                new Vector3(0f, 0f, outerRadius),

                new Vector3(innerRadius,0f,0.5f*outerRadius),

                new Vector3(innerRadius,0f,-0.5f*outerRadius),

                new Vector3(0f,0f,-outerRadius),

                new Vector3(-innerRadius,0f,-0.5f*outerRadius),

                new Vector3(-innerRadius,0f,0.5f*outerRadius),

                new Vector3(0f, 0f, outerRadius),
        };

}

绘制三角形的时候代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum HexDirection

{

    NE,

    E,

    SE,

    SW,

    W,

    NW,

}
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer), typeof(MeshCollider))]
public class HexCell : MonoBehaviour
{

    private Mesh mesh;

    private List<Vector3> vertices;

    private List<int> triangles;



    private void Awake()

    {

        GetComponent<MeshFilter>().mesh = mesh = GetComponent<MeshCollider>().sharedMesh = new Mesh();

        GetComponent<MeshCollider>().convex = true;

        mesh.name = "Hex Cell";

        vertices = new List<Vector3>();

        triangles = new List<int>();

        Draw();

    }



    // Use this for initialization

    void Start()
    {



    }



    // Update is called once per frame

    void Update()
    {



    }

    /// <summary>

    /// 绘制地形

    /// </summary>

    public void Draw()

    {

        Clear();

        Vector3 center = Vector3.zero;

        for (HexDirection dir = HexDirection.NE; dir <= HexDirection.NW; dir++)

        {

            AddTriangle(center,

                    HexMetrics.corners[(int)dir],

                    HexMetrics.corners[(int)dir + 1]);

        }



        UpdateMesh();

    }



    /// <summary>

    /// 清空mesh数据

    /// </summary>

    private void Clear()

    {

        mesh.Clear();

        vertices.Clear();

        triangles.Clear();

    }

    /// <summary>

    /// 绘制mesh数据

    /// </summary>

    private void UpdateMesh()

    {

        mesh.vertices = vertices.ToArray();

        mesh.triangles = triangles.ToArray();

        mesh.RecalculateNormals();

        mesh.RecalculateBounds();

    }

    /// <summary>

    /// 添加三角形。

    /// </summary>

    /// <param name="v1"></param>

    /// <param name="v2"></param>

    /// <param name="v3"></param>

    private void AddTriangle(Vector3 v1, Vector3 v2, Vector3 v3)

    {

        int count = triangles.Count;

        vertices.Add(v1);

        triangles.Add(count++);

        vertices.Add(v2);

        triangles.Add(count++);

        vertices.Add(v3);

        triangles.Add(count++);

    }

}

在unity中随便挂在一个空对象上。就可以生成如下图:

接下来是构建地图网格:

从上图可以看出来如下规律:


1.同一行的相邻六边形的间距为2个内径的距离

2.两列六边形,在纵坐标上相差1.5个外径的距离

3.列数为奇数的六边形在横坐标上,会向右偏移1个内径的距离。

所以我们可以通过如下方式将队列上的坐标(x,y)转换为空间上的坐标:
    private Vector3 GetPos(int x, int y)

    {

        float posX = x;

        float posY = y;

        if ((y & 1) != 0)

        {

            posX += 0.5f;

        }

        Vector3 pos = new Vector3(2f * posX * HexMetrics.innerRadius, 0f, 1.5f * posY * HexMetrics.outerRadius);

        return pos;

    }
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Train : MonoBehaviour {

    public int col = 10;

    public int row = 10;
    private Vector3 GetPos(int x, int y)

    {

        float posX = x;

        float posY = y;

        if ((y & 1) != 0)

        {

            posX += 0.5f;

        }

        Vector3 pos = new Vector3(2f * posX * HexMetrics.innerRadius, 0f, 1.5f * posY * HexMetrics.outerRadius);

        return pos;

    }
    // Use this for initialization
    void Start () {
        for (int i = 0; i < col; i++) {

            for (int j = 0; j < row; j++)
            {
               Vector3 pos =  GetPos(i, j);
               GameObject Plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
               Plane.AddComponent<HexCell>();
               Plane.transform.position = pos;
               Plane.GetComponent<MeshRenderer>().material.color = new Color(i / col, (i + j) / (col + row), j / row);
            }
        }
	}

}


运行一下,我们就可以得到下面图片:

 

[个人学习博客谢谢关注](www.taoqy666.com)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值