寻路算法 Astar A星算法

2023-05-16


<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>首先是创建一些变量<pre name="code" class="javascript">private static _instance: Astar;

        static get instance(): Astar {
            if(!this._instance) {
                this._instance = new Astar();
            }
            return this._instance;
        }

        /**
         * 开放节点列表
         * */
        m_openList: Array<AstarPathStep>/* = new Array<AstarPathStep>()*/;

        /**
         * 关闭节点列表
         * */
        m_closeList: foxgame.HashMap = new foxgame.HashMap();

        /**
         * 横向移动一格的评分
         * */
        public static COST_HORIZONTAL = 20;

        /**
         * 竖向移动一格的路劲评分
         * */
        public static COST_VERTICAL = 10;

        /**
         * 斜向移动一格的路劲评分
         * */
        public static COST_DIAGONAL = 12;
        
        public constructor() {

        }
        
        /**
     * 地图类对象
     * */
        public tileMap: foxgame.TiledMap;


  
<span style="white-space:pre">	</span>/**
    	  * 寻路   开始寻路计算
    	  * */
        public findPath(startPos: egret.Point,endPos: egret.Point,tileMap: foxgame.TiledMap) {
            
            this.tileMap = tileMap;//地图
            
            var isFind = false;

            var starTime = egret.getTimer();//开始寻路的时间

            if(egret.Point.distance(startPos,endPos) < 0.5) {
                if(Global.logLevel > Global.logLevelInfo) {
                    console.log("You're already there! :P");
                }
                return null;
            }

            if(tileMap.isPass(endPos.x,endPos.y) != true) {
                if(Global.logLevel > Global.logLevelInfo) {
                    console.log("blocf or beyond the range");
                }
                return null;
            }
            
            if (!this.m_openList)
                this.m_openList = new Array<AstarPathStep>();

            this.m_closeList.clear();

            var endStep = new AstarPathStep(endPos);
            var startStep = new AstarPathStep(startPos);
            
            startStep.m_hScore = this.getHValue(startStep,endStep);
            this.insertAndSort(startStep);

            var curStep: AstarPathStep;
            do { 
                var elapesTime = egret.getTimer() - starTime;
//                if(elapesTime > 600) {
//                    isFind = false;
//                    //寻路超时
//                    break;
//                }
                curStep = this.m_openList.shift();
                curStep.setInClose(true);
                curStep.setInOpen(false);
                this.m_closeList.put(curStep.m_tilePos.x + "_" + curStep.m_tilePos.y,true);

                if(curStep.isEqualByPos(endPos)) {
                    isFind = true;
                    break;
                }

                var arundNodes = this.getAroundsNode(curStep.m_tilePos);
                for(var i = 0;i < arundNodes.length;i++) {
                    var onePos = arundNodes[i];
                    var nextStep = new AstarPathStep(onePos);
                    var gValue = this.getGValue(curStep,nextStep);
                    var hValue = this.getHValue(endStep,nextStep);

                    if(nextStep.m_inOpen == true) {
                        if(gValue < nextStep.m_gScore) {
                            nextStep.m_gScore = gValue;
                            nextStep.m_hScore = hValue;
                            nextStep.m_parent = curStep;
                            this.findAndSort(nextStep);
                        }
                    } else {
                        nextStep.m_gScore = gValue;
                        nextStep.m_hScore = hValue;
                        nextStep.m_parent = curStep;
                        this.insertAndSort(nextStep);
                    }
                }
                
            } while(this.m_openList.length > 0);

            if(isFind) {
                var path = this.createPath(curStep);
                //this.m_openList = new Array<AstarPathStep>();
                this.m_openList.length = 0;
                this.m_closeList.clear();
                return path;
            } else {
                //this.m_openList = new Array<AstarPathStep>();
                this.m_openList.length = 0;
                this.m_closeList.clear();
                return null;
            }
        }

创建路径

<span style="white-space:pre">	</span>public createPath(step: AstarPathStep) {
            var path: Array<egret.Point> = new Array<egret.Point>();
            do{
                if(step.m_parent != null){
                    var curPos: egret.Point = step.m_tilePos;
                    path.unshift(curPos);
                }
                step = step.m_parent;
            } while(step != null) 
            return path;
        }
那么AstarPathStep又是什么呢

export class AstarPathStep{
        m_tilePos: egret.Point;
        m_gScore: number = 0;
        m_hScore: number = 0;
        m_parent: AstarPathStep;
        m_inOpen = false;
        m_inClose = false;
        
        public constructor(tilePos: egret.Point) {
            this.m_tilePos = tilePos;
            this.m_parent = null;
        }

        /**
         * 返回这个点的f评分
         * */
        public fScore(): number {
            return this.m_gScore + this.m_hScore;
        }

        /**
         * 是同一个AstarPathStep
         * */
        public isEqual(setp: AstarPathStep): boolean {
            if(this.m_tilePos.x == setp.m_tilePos.x && this.m_tilePos.y == setp.m_tilePos.y) {
                return true;
            }
            return false;
        }

        /**
         * 是同一个点
         * */
        public isEqualByPos(pos: egret.Point): boolean {
            if(this.m_tilePos.x == pos.x && this.m_tilePos.y == pos.y) {
                return true;
            }
            return false;
        }

        /**
         * 设置为开放节点
         * */
        public setInOpen(flag) {
            this.m_inOpen = flag;
        }

        /**
         * 设置为关闭节点
         * */
        public setInClose(flag) {
            this.m_inClose = flag;
        }
    }
/**
         * 插入
         * */
        private insertAndSort(step: AstarPathStep) {
            step.setInOpen(true);
            var stepFScore = step.fScore();
            var openCount = this.m_openList.length;
            if(openCount == 0) {
                this.m_openList.push(step);
            } else {
                for(var i = 0;i < openCount;i++) {
                    var oneStep = this.m_openList[i];
                    if(stepFScore <= oneStep.fScore()) {
                        this.m_openList.splice(i,0,step);
                        return
                    }
                }
            }
        }
 /**
         * 返回移动方向
         * */
        
        public judgeNextDirection(curPos,nextPos): number {
            var p = new egret.Point(curPos.x - 1,curPos.y);
            if(egret.Point.distance(p,nextPos) < 0.1) {
                return EnumManager.DIRECTION_ENUM.DIR_LEFT;
            }
            var p = new egret.Point(curPos.x,curPos.y - 2);
            if(egret.Point.distance(p,nextPos) < 0.1) {
                return EnumManager.DIRECTION_ENUM.DIR_UP;
            }
            var p = new egret.Point(curPos.x + 1,curPos.y);
            if(egret.Point.distance(p,nextPos) < 0.1) {
                return EnumManager.DIRECTION_ENUM.DIR_RIGHT;
            }
            var p = new egret.Point(curPos.x,curPos.y + 2);
            if(egret.Point.distance(p,nextPos) < 0.1) {
                return EnumManager.DIRECTION_ENUM.DIR_DOWN;
            }
            var p = new egret.Point(curPos.x - 1 + curPos.y % 2,curPos.y - 1);
            if(egret.Point.distance(p,nextPos) < 0.1) {
                return EnumManager.DIRECTION_ENUM.DIR_UP_LEFT;
            }
            var p = new egret.Point(curPos.x + curPos.y%2,curPos.y - 1);
            if(egret.Point.distance(p,nextPos) < 0.1) {
                return EnumManager.DIRECTION_ENUM.DIR_UP_RIGHT;
            }
            var p = new egret.Point(curPos.x + curPos.y%2,curPos.y + 1);
            if(egret.Point.distance(p,nextPos) < 0.1) {
                return EnumManager.DIRECTION_ENUM.DIR_DOWN_RIGHT;
            }
            var p = new egret.Point(curPos.x - 1 + curPos.y%2,curPos.y+1);
            if(egret.Point.distance(p,nextPos) < 0.1) {
                return EnumManager.DIRECTION_ENUM.DIR_DOWN_LEFT;
            }
            console.log("方向解析失败");
            
            //方向解析失败后直接使用角度进行方向解析
            var angleSpeed: number = Math.atan2(curPos.y - nextPos.y,curPos.x - nextPos.x);
            var N = angleSpeed * 180 / Math.PI;
            if(N <= 20 && N >= -20) {
                return EnumManager.DIRECTION_ENUM.DIR_LEFT;
            } else if(N <= 110 && N >= 70) {
                return EnumManager.DIRECTION_ENUM.DIR_UP;
            } else if(N <= -170 || N >= 170) {
                return EnumManager.DIRECTION_ENUM.DIR_RIGHT;
            } else if(N <= -70 && N >= -110) {
                return EnumManager.DIRECTION_ENUM.DIR_DOWN;
            } else if(N < 70 && N > 20) {
                return EnumManager.DIRECTION_ENUM.DIR_UP_LEFT;
            } else if(N < 170 && N > 110) {
                return EnumManager.DIRECTION_ENUM.DIR_UP_RIGHT;
            } else if(N < -110 && N > -170) {
                return EnumManager.DIRECTION_ENUM.DIR_DOWN_RIGHT;
            } else if(N < -20 && N > -70) {
                return EnumManager.DIRECTION_ENUM.DIR_DOWN_LEFT;
            }
            return EnumManager.DIRECTION_ENUM.DIR_DOWN;
        }
        
    }
/**
         * 获取H值
         * */
        public getHValue(endStep: AstarPathStep,nextStep: AstarPathStep): number {
            var to0 = nextStep.m_tilePos.x * Astar.COST_HORIZONTAL + (Math.floor(nextStep.m_tilePos.y) % 2) * Astar.COST_HORIZONTAL / 2;
            var endTo0 = endStep.m_tilePos.x * Astar.COST_HORIZONTAL + (Math.floor(endStep.m_tilePos.y) % 2) * Astar.COST_HORIZONTAL / 2;
            return Math.abs(endTo0 - to0) + Math.abs(endStep.m_tilePos.y - nextStep.m_tilePos.y) * Astar.COST_VERTICAL;
        }
 /**
         * 获取G值
         * */
        public getGValue(curStep: AstarPathStep,nextStep: AstarPathStep): number {
            var extaScore = 0;
            var curPos = curStep.m_tilePos;
            var nextPos = nextStep.m_tilePos;

            var G = 0;
            if(curPos.y == nextPos.y) {//横向移动
                G = curStep.m_gScore + Astar.COST_HORIZONTAL;
            } else if(((curPos.y + 2) == nextPos.y) || ((curPos.y - 2) == nextPos.y)) {
                G = curStep.m_gScore + Astar.COST_VERTICAL * 2;
            } else {
                G = curStep.m_gScore + Astar.COST_DIAGONAL;
            }

            return G;
        }
 /**
         * 获取周围的节点
         * */
        public getAroundsNode(tpt: egret.Point): Array<egret.Point> {
            var aroundNodes: Array<egret.Point> = new Array();
            var p: egret.Point = new egret.Point();
            //左下
            p = new egret.Point(tpt.x - 1 + tpt.y % 2,tpt.y + 1);
            if(this.isWalkable(p) && this.isInClosed(p) == false) {
                aroundNodes.push(p);
            }
            p = new egret.Point(tpt.x + tpt.y % 2,tpt.y - 1);
            //右上
            if(this.isWalkable(p) && this.isInClosed(p) == false) {
                aroundNodes.push(p);
            }

            var p: egret.Point = new egret.Point();
            //下
            p.x = tpt.x
            p.y = tpt.y + 2;
            if(this.isWalkable(p) && this.isInClosed(p) == false) {
                aroundNodes.push(p);
            }
            //左
            p = new egret.Point(tpt.x - 1,tpt.y);
            if(this.isWalkable(p) && this.isInClosed(p) == false) {
                aroundNodes.push(p);
            }
            //右
            p = new egret.Point(tpt.x + 1,tpt.y);
            if(this.isWalkable(p) && this.isInClosed(p) == false) {
                aroundNodes.push(p);
            }
            //上
            p = new egret.Point(tpt.x,tpt.y - 2);
            if(this.isWalkable(p) && this.isInClosed(p) == false) {
                aroundNodes.push(p);
            }
            p = new egret.Point(tpt.x - 1 + (tpt.y % 2),tpt.y - 1);
            //左上
            if(this.isWalkable(p) && this.isInClosed(p) == false) {
                aroundNodes.push(p);
            }
            //右下
            p = new egret.Point(tpt.x + (tpt.y % 2),tpt.y + 1);
            if(this.isWalkable(p) && this.isInClosed(p) == false) {
                aroundNodes.push(p);
            }
            return aroundNodes;
        }








本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

寻路算法 Astar A星算法 的相关文章

  • android.os.deadObjectException异常

    deadObjectException异常 xff0c 说明应用的service已经停止 xff0c 要么是从操作系统中丧生 xff0c 要么从应用程序中终止
  • 2038问题

    2038年一月19号 xff0c 星期二 xff0c 凌晨3点14分7秒钟的时候 xff0c 如果Linux程序员会做恶梦的话 xff0c 那么梦的内容一定是关于这个日期的 xff0c 在这一秒钟滑过后 xff0c 凡是安装着linux的计
  • ChkBugReport工具for Android

    关于这个工具 xff0c 找到的资料都比较旧了 xff0c 貌似是索尼移动的开发人员开发的 xff0c 2014年左右的文章比较多 xff0c 应该是那个时候索尼移动还是比较鼎盛的时期吧 现在已经很少看到关于这个工具的文章了 xff0c G
  • kernel panic

    Linux kernel panic是很难定位和排查的重大故障 一旦系统发生了kernel panic xff0c 相关的日志信息非常少 xff0c 而一种常见的排查方法 重现法 又很难实现 xff0c 因此遇到kernel panic的问
  • PS域业务与CS域业务的区别

    1 CS和PS是针对核心网部分而言的 xff0c 两者的不同在于交换方式 CS是电路交换 xff0c 通信之前 xff0c 资源预留 xff0c 不同用户独占各自分配的资源 xff0c 没有统计复用 PS是包交换 xff0c 不同的用户可以
  • sh_脚本语法

    介绍 xff1a 1 开头 程序必须以下面的行开始 xff08 必须方在文件的第一行 xff09 xff1a bin sh 符号 用来告诉系统它后面的参数是用来执行该文件的程序 在这个例子中我们使用 bin sh来执行程序 当编写脚本完成时
  • 【深度学习系列(三)】:基于CNN+seq2seq公式识别系统实现 (1)

    这段时间一直在做公式识别相关的项目 xff0c 尝试了传统的方法 xff0c 效果不怎么好 想到能不能使用深度学习的方法进行相关方法 然后在github找到了相关代码 xff0c 这里做下分析 具体github地址 xff1a GitHub
  • 困惑多年,为什么printf可以重定向?

    很多人在用printf函数进行串口打印的时候 xff0c 都会被告知需要重定向fputc函数 xff08 别的平台可能不是这个函数 xff09 xff0c 让字符串数据输出到指定串口 xff0c 按照网上的教程也能很快解决 但是却没人告诉你
  • 多线程并发编程

    文章目录 多线程并发编程一 多线程带来的问题相关概念 二 互斥1 互斥与互斥量2 申请互斥量I 静态方法申请互斥量 xff1a II 动态方法申请互斥量 xff1a 3 利用互斥量加锁与解锁4 销毁互斥量5 互斥量综合应用 模拟抢票6 互斥
  • 【嵌入式】---- 串口UART波形分析

    串口参数的配置 波特率 xff08 bit s xff09 xff1a 大多数使用115200 但有些芯片特殊 xff0c 具体要看数据手册中波特率的容错率 比如中微的CMS32L051就不支持115200bps 停止位 xff1a 一般选
  • 手把手教你用JAVA实现“语音合成”功能(文字转声音)标贝科技

    手把手教你用JAVA实现 语音合成 功能 xff08 文字转声音 xff09 标贝科技 前言 什么是语音合成 xff1f 将文本转换成自然流畅的语音 xff0c 本篇文章将介绍 实时在线合成 xff08 文本长度不得超过1024字节 xff
  • cv::imread(cv::String const&, int)’未定义的引用

    在 Makefile文件的195 行 LIBRARIES 43 61 opencv core opencv highgui opencv imgproc 后面添加 xff1a opencv imgcodecs opencv videoio修
  • 【C/C++】C++ 网络多线程编程

    关键词 xff1a C C 43 43 网络编程 多线程 套接字 UDP 前言 学习C 43 43 网络编程多线程编程的目的 xff1a 巩固C 43 43 xff1b 由于C 43 43 大多用于服务器 xff0c 因此网络和多线程是进入
  • 在ubuntu20.04上配置VINS_Fusion(亲测有效,一应俱全)

    最近在做科研训练的时候配置了HKUST Aerial Robotics实验室的VINS Fusion代码项目 xff0c 经历了一些编译报错的问题 xff0c 在网上查找的时候博客内容良莠不齐 xff0c 且实质针对性意见不多 xff0c
  • 无人机项目跟踪记录二十五--无线接收模块的输入输出

    无线接收模块的功能是接收无线遥控器的命令 xff08 应该对应的是无人机上面的无线接收芯片 xff09 xff0c 无人机根据接收的指令进行不同的处理 用同样方法 xff0c 无线接收模块包含的函数是 xff1a Nrf Irq void
  • UDP校验和及代码

    UDP校验和采用反码求和 xff1a 两数相加 xff0c 把超出16位加入到第0位 校验和算法 unsigned short UDPCheck unsigned short data int len int carryBit 61 0 i
  • ROS Moveit:rviz和gazebo仿真出现rviz规划后gazebo没有反应

    在用rviz规划后 xff0c 警告 WARN 1649654675 728414350 42 937000000 Failed to validate trajectory couldn 39 t receive full current
  • Libcurl实现HTTP/HTTPS客户端(支持get、post、保持session)

    前面的文章 Libcurl编译指南 Android和Windows系统 已经就libcurl在Windows和Android系统编做了详细的说明 本文档用C C 43 43 实现简单的HTTP HTTPS客户端 xff0c 支持get和po
  • 基于uart的RS232和RS485总线

    我们之前讲uart的时候就已经提过一个问题 xff0c 就是它并不是直接连接到SOC里面的 xff0c 而是经过了一个芯片的转换 这个芯片的转换就是和我们要说的rs232 485总线有关的 RS232和RS485总线其实本质就是uart 只
  • c语言

    一 c基础 1 1 一个函数遇到return语句就终止了 1 2 system系统调用 xff1a 用命令打开计算器 记事本等 xff0c windows和linux下命令不同 xff0c 需要头文件 xff08 stdlib h xff0

随机推荐