A* (AStar) 寻路

打印 上一主题 下一主题

主题 1922|帖子 1922|积分 5766

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
//调用工具类获取路线
        let route = AStarSearch.getRoute(start_point, end_point, this.mapFloor.map_point);
map_point 是所有可走点的集合
  1. import { _decorator, Component, Node, Prefab, instantiate, v3, Vec2 } from 'cc';
  2. import { oops } from "../../../../../extensions/oops-plugin-framework/assets/core/Oops";
  3. import { GameWorld } from "../../../GameWorld";
  4. import { MapFloor, RowColData } from "../../../../Scripts/MapEditor/MapFloor";
  5. export class Point {
  6.     x: number;
  7.     y: number;
  8.     constructor(x: number, y: number) {
  9.         this.x = x;
  10.         this.y = y;
  11.     }
  12.     G: number = 0;   //G = 从起点A,沿着产生的路径,移动到网格上指定方格的移动耗费。
  13.     H: number = 0;   //H = 从网格上那个方格移动到终点B的预估移动耗费
  14.     F: number = 0;   //F = G + H
  15.     father: Point = null;   //这个点的上一个点,通过回溯可以找到起点
  16.     is_close: boolean = false;   //是否关闭搜索
  17. }
  18. export class AStarSearch {
  19.     static start: Point = null;      //起点
  20.     static end: Point = null;        //终点
  21.     static map: Map<string, Point> = null;   //地图point
  22.     static openSet: Set<Point> = new Set();  //开放队列
  23.     static pppp: Point = null;       //执行完寻路,它就有值了,除非没找到
  24.     /**
  25.      * 获取路线 (此寻路不走斜线)
  26.      */
  27.     static getRoute(start: Point, end: Point, map_point: Map<string, { row: number, col: number }>): Point[] {
  28.         //清空上次寻路,并赋值
  29.         this.is_find = false;
  30.         this.openSet.clear();
  31.         this.pppp = null;
  32.         this.start = { ...start };
  33.         this.end = { ...end };
  34.         this.map = new Map<string, Point>();
  35.         map_point.forEach((value, key) => {
  36.             let point = new Point(value.row, value.col);
  37.             this.map.set(key, point);
  38.         });
  39.         let route = new Array<Point>();
  40.         let keyStr = this.start.x + "_" + this.start.y;
  41.         if (!this.map.has(keyStr)) {
  42.             return route;
  43.         }
  44.         this.map.get(keyStr).G = 0;       //起点的G是0
  45.         //开始寻路
  46.         try {
  47.             this.search(this.start);     //内存不够会报错,一般是起点或终点封闭
  48.         } catch (error) {
  49.             console.warn("位置不对", error);
  50.             return route;
  51.         }
  52.         if (this.pppp) {
  53.             this.getFather(this.pppp, route);
  54.         }
  55.         return route;
  56.     }
  57.     /**
  58.      * 寻路
  59.      */
  60.     static is_find = false;    //是否已经找到路线
  61.     static search(point: Point) {
  62.         if (point.x == this.end.x && point.y == this.end.y) {
  63.             this.is_find = true;
  64.             this.pppp = point;
  65.             return;
  66.         }
  67.         let arr = this.getAround(point);
  68.         arr.forEach(p => {
  69.             this.setFather(p, point);
  70.         });
  71.         //arr按照F排序 从小到大
  72.         this.openSet = new Set([...this.openSet].sort(this.compare));
  73.         //递归继续找
  74.         this.openSet.forEach((pp, index, arr) => {
  75.             if (pp.is_close) {        //删除没用的
  76.                 this.openSet.delete(pp);
  77.             }
  78.             if (!this.is_find) {
  79.                 this.search(pp);
  80.             }
  81.         });
  82.     }
  83.     /**
  84.      * 获取周围4个点,上下左右
  85.      */
  86.     static getAround(point: Point) {
  87.         point.is_close = true;
  88.         let arr = new Array<Point>();
  89.         let index: string;
  90.         let p: Point;
  91.         //上、下、左、右
  92.         let aroundPos = [
  93.             { x: point.x, y: point.y - 1 },
  94.             { x: point.x, y: point.y + 1 },
  95.             { x: point.x - 1, y: point.y },
  96.             { x: point.x + 1, y: point.y }
  97.         ]
  98.         aroundPos.forEach(point => {
  99.             index = point.x + "_" + point.y;
  100.             p = this.map.get(index);
  101.             if (p && !p.is_close) {
  102.                 arr.push(p);
  103.                 this.openSet.add(p);
  104.             }
  105.         })
  106.         return arr;
  107.     }
  108.     /**
  109.      * point换父亲,并重新计算G、H、F
  110.      */
  111.     static setFather(son: Point, father: Point) {
  112.         if (!son.father || son.father.G > father.G) {
  113.             son.father = father;
  114.             son.G = son.father.G + 1;
  115.             son.H = Math.abs(son.x - this.end.x) + Math.abs(son.y - this.end.y);
  116.             son.F = son.G + son.H;
  117.         }
  118.     }
  119.     /**
  120.      * 比较器
  121.      */
  122.     static compare(p1: Point, p2: Point) {
  123.         if (p1.F > p2.F) {
  124.             return 1;
  125.         } else {
  126.             return -1;
  127.         }
  128.     }
  129.     /**
  130.      * 递归 把祖宗放进route里面
  131.      */
  132.     static getFather(point: Point, route: Array<Point>) {
  133.         let father = point.father;
  134.         if (father) {
  135.             this.getFather(father, route);
  136.         }
  137.         route.push(point);
  138.     }
  139. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

罪恶克星

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表