ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

CocosCreator_项目中运用A*算法做寻路设计

2021-01-21 20:34:32  阅读:191  来源: 互联网

标签:node return GridNode CocosCreator 算法 let 寻路 public row


A*寻路算法总体来说还是比较简单和高效的,这里对在项目中的使用记录下,源码如下

设计一个二维数组类ArrayList.ts

/**
* Autor: Created by 李清风 on 2020-11-17.
* Desc: ArrayList
*/
export class ArrayList {
    private _list: [any[]];
    private _row;//矩阵行
    private _colums;//矩阵列

    public constructor(rows: number, colums: number, defalut: any = 0) {
        this._list = [[]];
        this._row = rows;
        this._colums = colums;
        this.initRows(rows);
        this.initColumns(colums, defalut);
    }

    //初始化数组行
    initRows(rows: number) {
        if (rows < 1) {
            return;
        }
        for (let i = 0; i < this._row; i++) {
            let item:any[] = [];
            this._list.push(item);
        }
    }

    //初始化数组列
    initColumns(columns: number, value: any) {
        if (columns < 1) {
            return;
        }
        for (let i = 0; i < this._list.length; i++) {
            for (let j = 0; j < columns; j++) {
                this._list[i].push(value)
            }
        }
    }

    getValue(rows: number, colums: number) {
        if (rows < 0 || colums < 0 || rows >= this._row || colums >= this._colums) {
            console.error("IndexOutOfRangeException: Index was outside the bounds of the array.")
            return null;
        }
        return this._list[rows][colums];
    }

    setValue(rows: number, colums: number, value) {
        if (rows < 0 || colums < 0 || rows >= this._row || colums >= this._colums) {
            console.error("IndexOutOfRangeException: Index was outside the bounds of the array.")
            return;
        }
        this._list[rows][colums] = value;
    }

    getArrayList(): Array<Array<any>> {
        return this._list;
    }

}

设计一个优先级队列PriorityQueue.ts

import { GridNode } from "./GridNode";


/**
* Autor: Created by 李清风 on 2020-11-17.
* Desc: PriorityQueue
*/
export class PriorityQueue {

    private nodes: GridNode[] = [];


    public Length() {
        return this.nodes.length;
    }

    public Contains(node: GridNode) {
        return this.nodes.includes(node);
    }

    public First(): GridNode {
        if (this.nodes.length > 0) {
            return this.nodes[0];
        }
        return null;
    }

    public Add(node: GridNode) {
        this.nodes.push(node);
        this.sort();
    }

    public Remove(node: GridNode) {
        let index = this.nodes.indexOf(node);
        if (index > -1) {
            this.nodes.splice(index, 1);
        }
        this.sort();
    }

    private sort() {
        let sortCallFunc = (a, b) => {
            if (a.estimatedCost < b.estimatedCost) {
                return -1;
            }

            if (a.estimatedCost > b.estimatedCost) {
                return 1;
            }

            return 0;
        }
        this.nodes.sort(sortCallFunc)
    }
}

设计一个节点格子类GridNode.ts

/**
* Autor: Created by 李清风 on 2020-11-17.
* Desc: GridNode
*/
export class GridNode {

    public nodeTotalCost: number;
    public estimatedCost: number;
    public bObstacle: boolean;
    public parent: GridNode;
    public position: cc.Vec2; //矩阵行列式,也可代表x,y轴

    public constructor() {
        this.estimatedCost = 0;
        this.nodeTotalCost = 1;
        this.bObstacle = false;
        this.parent = null;
    }

    public initWithPos(pos: cc.Vec2) {
        this.estimatedCost = 0;
        this.nodeTotalCost = 1;
        this.bObstacle = false;
        this.parent = null;
        this.position = pos;
    }

    public MarkAsObstacle() {
        this.bObstacle = true;
    }
}

 

设计管理格子的管理类GridManager.ts

import { ArrayList } from "./ArrayList";
import { GridNode } from "./GridNode";

/**
* Autor: Created by 李清风 on 2020-11-17.
* Desc: 地图网格化管理器
*/

export class GridManager {

    private static _instance: GridManager;
    public static getInstance(): GridManager {
        if (GridManager._instance == null) {
            GridManager._instance = new GridManager();
        }
        return GridManager._instance;
    }

    public numOfRows: number; //行数
    public numOfColumns: number;//列数
    public girdCellSize: number;
    public showGrid: boolean;

    nodes: ArrayList;
    public obstacleList: any[];


    public init(row: number, column: number, mapData: any) {
        if (!mapData) {
            console.error('地图数据加载失败');
            return;
        }
        this.numOfRows = row; // 53 (0,52)
        this.numOfColumns = column; //45(0-44)
        this.CalcuateGirdNodes(mapData);
    }

    /**
     * 初始化网格da
     * @param mapData json数据
     * @param 注:网格是严格按照x,y对应来进行初始化的,但是遍历map需要额外处理下
     */
    public CalcuateGirdNodes(mapData: any) {
        this.nodes = new ArrayList(this.numOfRows, this.numOfColumns);
        for (let i = 0; i < this.numOfColumns; i++) {
            for (let j = 0; j < this.numOfRows; j++) {
                let node: GridNode = new GridNode();
                node.initWithPos(cc.v2(j, i))
                //BlockType.disable 自己设计的标签,不可行走
                //BlockType.occlusion 障碍物
                //BlockType.Basket 其他
                if (mapData[i][j] == BlockType.disable || mapData[i][j] == BlockType.occlusion ||
                    mapData[i][j] == BlockType.Basket) {
                    node.MarkAsObstacle();
                }
                this.nodes.setValue(j, i, node);
            }
        }
    }

    private GetRow(pos: cc.Vec2) {
        let row = pos.x
        return row;
    }

    private GetColumn(pos: cc.Vec2) {
        let colums = pos.y;
        return colums;
    }

    private GetGridNodeByRowColumn(row: number, column: number) {
        return this.nodes.getArrayList()[row][column];
    }


    /**
     * 取8个点
     * @param node 
     * @param neighbors 
     */
    public GetNeighbours(node: GridNode, neighbors: GridNode[]) {
        let neighborPos: cc.Vec2 = node.position;
        let row = this.GetRow(neighborPos); // 26
        let colum = this.GetColumn(neighborPos); //20
        //左
        let leftNodeRow = row - 2;
        let leftNodeColum = colum;
        this.AssignNeighbour(leftNodeRow, leftNodeColum, neighbors);
        //右
        leftNodeRow = row + 2;
        leftNodeColum = colum;
        this.AssignNeighbour(leftNodeRow, leftNodeColum, neighbors);
        //上
        leftNodeRow = row;
        leftNodeColum = colum + 1;
        this.AssignNeighbour(leftNodeRow, leftNodeColum, neighbors);
        //下
        leftNodeRow = row;
        leftNodeColum = colum - 1;
        this.AssignNeighbour(leftNodeRow, leftNodeColum, neighbors);
        //左上
        leftNodeRow = row - 1;
        leftNodeColum = colum;
        this.AssignNeighbour(leftNodeRow, leftNodeColum, neighbors);
        //右上
        leftNodeRow = row + 1;
        leftNodeColum = colum;
        this.AssignNeighbour(leftNodeRow, leftNodeColum, neighbors);
        //左下
        leftNodeRow = row - 1;
        leftNodeColum = colum - 1;
        this.AssignNeighbour(leftNodeRow, leftNodeColum, neighbors);
        //右下
        leftNodeRow = row + 1;
        leftNodeColum = colum - 1;
        this.AssignNeighbour(leftNodeRow, leftNodeColum, neighbors);
    }


    private AssignNeighbour(row: number, colum: number, neighbors: GridNode[]) {
        if (row != -1 && colum != -1 && row < this.numOfRows && colum < this.numOfColumns) {
            let nodeToAdd: GridNode = this.GetGridNodeByRowColumn(row, colum);
            if (!nodeToAdd.bObstacle) {
                neighbors.push(nodeToAdd);
            }
        }
    }

}

设计核心的脚本AStar.ts

/**
* Autor: Created by 李清风 on 2020-11-17.
* Desc: A*
*/

import { GridManager } from "./GridManager";
import { GridNode } from "./GridNode";
import { PriorityQueue } from "./PriorityQueue";

export class AStar {

    private static openList: PriorityQueue;
    private static closeList: PriorityQueue;

    private static NodeCost(a: GridNode, b: GridNode): number {
        let vecCost: cc.Vec2 = a.position.sub(b.position);
        return vecCost.mag();
    }

    public static FindPath(start: GridNode, goal: GridNode): any {
        AStar.openList = new PriorityQueue();
        AStar.openList.Add(start);
        AStar.closeList = new PriorityQueue();
        start.nodeTotalCost = 0;
        start.estimatedCost = AStar.NodeCost(start, goal);
        let node: GridNode = null;
        while (AStar.openList.Length() != 0) {
            node = AStar.openList.First();
            if ((node.position.x == goal.position.x) && (node.position.y == goal.position.y)) {
                return AStar.CalculatePath(node);
            }
            let neighbours: GridNode[] = [];
            GridManager.getInstance().GetNeighbours(node, neighbours);
            for (let i = 0; i < neighbours.length; i++) {
                let neighbourNode: GridNode = neighbours[i];
                if (!AStar.closeList.Contains(neighbourNode)) {
                    let cost: number = AStar.NodeCost(node, neighbourNode);
                    let totalCost = node.nodeTotalCost + cost;
                    let neighbourNodeEstCost = AStar.NodeCost(neighbourNode, goal);
                    neighbourNode.nodeTotalCost = totalCost;
                    neighbourNode.estimatedCost = totalCost + neighbourNodeEstCost;
                    neighbourNode.parent = node;
                    if (!AStar.openList.Contains(neighbourNode)) {
                        AStar.openList.Add(neighbourNode);
                    }
                }
            }
            AStar.closeList.Add(node);
            AStar.openList.Remove(node);
        }
        if ((node.position.x == goal.position.x) && (node.position.y == goal.position.y)) {
            console.error("Arrived Goal Path Not Found");
            return null;
        }
        return AStar.CalculatePath(node);
    }

    private static CalculatePath(node: GridNode): any {
        let list: GridNode[] = [];
        while (node != null) {
            list.push(node);
            node = node.parent;
        }
        list.reverse();
        return list;
    }
}

 

标签:node,return,GridNode,CocosCreator,算法,let,寻路,public,row
来源: https://www.cnblogs.com/makeamericagreatagain/p/14310283.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有