日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

从零开始做一个SLG游戏(一):六边形网格

發布時間:2024/8/26 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从零开始做一个SLG游戏(一):六边形网格 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文的主要工作是六邊形網格的繪制。
?


如圖所示。六邊形有6個方向,6個頂點,同時定義中心點到邊的最短距離為內徑innerRadius,定義中心點到頂點的距離為外徑outerRadius。

六邊形可以拆分為6個等邊三角形,所以很容易得出:
?


定義游戲中六邊形的邊長(即外徑)為10.

手游賬號買號用一個靜態類以及一個枚舉將這些定義下來:

  • using UnityEngine;
  • public static class HexMetrics
  • {
  • ? ?? ???/// <summary>
  • ? ?? ???/// 外徑,中心到頂點距離
  • ? ?? ???/// </summary>
  • ? ?? ???public const float outerRadius = 10f;
  • ? ?? ???/// <summary>
  • ? ?? ???/// 內徑,中心到邊距離,0.866025404為二分之根號三的近似值
  • ? ?? ???/// </summary>
  • ? ?? ???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)
  • ? ?? ???};
  • }
  • /// <summary>
  • /// 六邊形的方向
  • ///? ?? ?? ?? ?? ? NW /\ NE
  • ///? ?? ?? ?? ?? ? W |??|E
  • ///? ?? ?? ?? ?? ? SW \/ SE
  • /// </summary>
  • public enum HexDirection
  • {
  • ? ?? ???NE,
  • ? ?? ???E,
  • ? ?? ???SE,
  • ? ?? ???SW,
  • ? ?? ???W,
  • ? ?? ???NW,
  • }
  • 復制代碼


    之后開始寫關于圖片繪制的代碼:

    將六邊形分解為6個等邊三角形,三角形的三個頂點分別為六邊形中心點,以及六邊形一條邊的兩個頂點:

    即HexMetrics.corners和HexMetrics.corners[i+1]

    因為第六條邊的時候,i=5,i+1=6,corners[6]不存在,所以在定義里加一個coners[6],和coners[0]相等:
    ?

  • 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),
  • ? ?? ???};
  • 復制代碼


    所以繪制三角形的時候,代碼可以寫成這樣:

    ? ?? ???

  • /// <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();
  • ? ?? ???}
  • 復制代碼


    然后貼上全部代碼:
    ?

  • [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;
  • ? ?? ???}
  • 復制代碼


    ? ?? ???
    為了便于區分,再將網格的顏色變一下:
    ?

  • cell.GetComponent<MeshRenderer>().material.color = new Color(posX / width, (posX + posY) / (height + width), posY / height);
  • 復制代碼


    一個六邊形的網格地圖的雛形就做好了,運行一下,我們就可以得到下面圖片:
    ?

    總結

    以上是生活随笔為你收集整理的从零开始做一个SLG游戏(一):六边形网格的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。