寻路算法 Astar A星算法

来源:互联网 发布:linux 安装服务 编辑:程序博客网 时间:2024/05/10 20:22
<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;        }








0 0
原创粉丝点击