zoukankan      html  css  js  c++  java
  • 小妖精的完美游戏教室——人工智能,A*算法,导航网络篇

    //================================================================
    //
    // Copyright (C) 2017 Team Saluka
    // All Rights Reserved
    //
    // Author:小妖精Balous
    //
    //================================================================

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

    namespace Saruka
    {
    /// <summary>
    /// 导航网格
    /// </summary>
    public class NavGrid : MonoBehaviour
    {
    /// <summary>
    /// 景物层级,用来建立导航网格
    /// </summary>
    public LayerMask scapeMask;
    /// <summary>
    /// 导航网格大小
    /// </summary>
    public Vector2 navGridSize;
    /// <summary>
    /// 单个网格半径
    /// </summary>
    public float gridRadius;
    /// <summary>
    /// 单个网格直径
    /// </summary>
    float gridDiameter;
    /// <summary>
    /// 网格结点
    /// </summary>
    public NavNode[,] grids
    {
    private set;
    get;
    }
    /// <summary>
    /// X轴方向网格数量
    /// </summary>
    public int gridCountX
    {
    private set;
    get;
    }
    /// <summary>
    /// Y轴方向网格数量
    /// </summary>
    public int gridCountY
    {
    private set;
    get;
    }

    /// <summary>
    /// 创建导航网格
    /// </summary>
    void CreateNavGrid()
    {
    gridDiameter = gridRadius * 2;
    gridCountX = Mathf.RoundToInt(navGridSize.x / gridDiameter);
    gridCountY = Mathf.RoundToInt(navGridSize.y / gridDiameter);

    grids = new NavNode[gridCountX, gridCountY];

    //导航网格左下角,平面直角坐标系
    Vector3 navGridBottomLeft = transform.position - Vector3.right * navGridSize.x / 2 - Vector3.up * navGridSize.y / 2;

    //创建网格
    for (int x = 0; x < gridCountX; x++)
    for (int y = 0; y < gridCountY; y++)
    {
    //网格中心坐标
    Vector3 gridCenter = navGridBottomLeft + Vector3.right * (x * gridDiameter + gridRadius) + Vector3.up * (y * gridDiameter + gridRadius);
    bool isWalkable = !(Physics2D.CircleCast(new Vector2(gridCenter.x, gridCenter.y), gridRadius, Vector2.zero, 0.0f, scapeMask));
    grids[x, y] = new NavNode(gridCenter, isWalkable, x, y);
    }
    }

    /// <summary>
    /// 获得世界坐标所在的结点
    /// </summary>
    /// <param name="worldPosition">世界坐标</param>
    /// <returns>结点</returns>
    public NavNode NavNodeFromWorldPosition(Vector3 worldPosition)
    {
    worldPosition -= transform.position;
    float percentX = Mathf.Clamp01((worldPosition.x + navGridSize.x / 2) / navGridSize.x);
    float percentY = Mathf.Clamp01((worldPosition.y + navGridSize.y / 2) / navGridSize.y);
    int x = Mathf.RoundToInt((gridCountX - 1) * percentX);
    int y = Mathf.RoundToInt((gridCountY - 1) * percentY);
    return grids[x, y];
    }

    public List<NavNode> GetNeighborNodes(NavNode navNode)
    {
    List<NavNode> neighborNodes = new List<NavNode>();

    for (int x = -1; x <= 1; x++)
    {
    for (int y = -1; y <= 1; y++)
    {
    if (x == 0 && y == 0) continue;

    int checkX = navNode.gridX + x;
    int checkY = navNode.gridY + y;
    if (checkX >= 0 && checkX < gridCountX && checkY >= 0 && checkY < gridCountY) neighborNodes.Add(grids[checkX, checkY]);
    }
    }
    return neighborNodes;
    }

    void OnDrawGizmos()
    {
    //导航网格边框
    Gizmos.DrawWireCube(transform.position, new Vector3(navGridSize.x, navGridSize.y, 1));

    if(grids != null)
    {
    foreach(NavNode node in grids)
    {
    Gizmos.color = (node.isWalkable) ? new Color(1, 1, 1, 0.4f) : new Color(1, 0, 0, 0.4f);
    Gizmos.DrawCube(node.worldPosition, Vector3.one * (gridDiameter - 0.03f));
    }
    }
    }

    // Use this for initialization
    void Start()
    {
    CreateNavGrid();
    }
    }
    }

  • 相关阅读:
    Java基础教程——Object类
    Java之从头开始编写简单课程信息管理系统
    动手动脑之文件流
    doc四则运算
    Java异常处理的方法
    动手动脑-异常处理
    动手动脑-Java的继承与多态
    跟踪某个类中创建对象的个数
    动手动脑--类与对象
    动手动脑
  • 原文地址:https://www.cnblogs.com/balous/p/7498692.html
Copyright © 2011-2022 走看看