一 演示效果

二  参考教程

《ActionScript3.0 高级动画教程》 + 源码

http://download.csdn.net/download/zhengchengpeng/7756023

三 AStar源码

Main.ts新建Game,即可看Demo

  this.addChild(new Game())

源码地址:

https://files.cnblogs.com/files/gamedaybyday/astar_ts.rar

AStar核心类

/**
* A星寻路
* @author chenkai
* @since 2017/11/3
*/
namespace astar{
export class AStar
{
private _open:Array<any>; //待考察表
private _closed:Array<any>; //已考察表
private _grid:astar.Grid; //网格
private _endNode:Node; //终点Node
private _startNode:Node; //起点Node
private _path:Array<any>; //保存路径
private _heuristic:Function; //寻路算法
private _straightCost:number = 1.0; //上下左右走的代价
private _diagCost:number = Math.SQRT2; //斜着走的代价 public constructor()
{
//this._heuristic = this.manhattan;
//this._heuristic = this.euclidian;
this._heuristic = this.diagonal;
} //寻路
public findPath(grid:Grid):boolean
{
this._grid = grid;
this._open = [];
this._closed = []; this._startNode = this._grid.startNode;
this._endNode = this._grid.endNode; this._startNode.g = ;
this._startNode.h = this._heuristic(this._startNode);
this._startNode.f = this._startNode.g + this._startNode.h; return this.search();
} //查找路径
public search():boolean
{
var node:Node = this._startNode;
while(node != this._endNode)
{
var startX = Math.max(, node.x - );
var endX = Math.min(this._grid.numCols - , node.x + );
var startY = Math.max(, node.y - );
var endY = Math.min(this._grid.numRows - , node.y + ); for(var i = startX; i <= endX; i++)
{
for(var j = startY; j <= endY; j++)
{
//不让斜着走
if(i != node.x && j != node.y){
continue;
} var test:Node = this._grid.getNode(i, j);
if(test == node ||
!test.walkable ||
!this._grid.getNode(node.x, test.y).walkable ||
!this._grid.getNode(test.x, node.y).walkable)
{
continue;
} var cost:number = this._straightCost;
if(!((node.x == test.x) || (node.y == test.y)))
{
cost = this._diagCost;
}
var g = node.g + cost * test.costMultiplier;
var h = this._heuristic(test);
var f = g + h;
if(this.isOpen(test) || this.isClosed(test))
{
if(test.f > f)
{
test.f = f;
test.g = g;
test.h = h;
test.parent = node;
}
}
else
{
test.f = f;
test.g = g;
test.h = h;
test.parent = node;
this._open.push(test);
}
}
}
for(var o = ; o < this._open.length; o++)
{
}
this._closed.push(node);
if(this._open.length == )
{
console.log("AStar >> no path found");
return false
} let openLen = this._open.length;
for(let m=;m<openLen;m++){
for(let n=m+;n<openLen;n++){
if(this._open[m].f > this._open[n].f){
let temp = this._open[m];
this._open[m] = this._open[n];
this._open[n] = temp;
}
}
} node = this._open.shift() as Node;
}
this.buildPath();
return true;
} //获取路径
private buildPath():void
{
this._path = new Array();
var node:Node = this._endNode;
this._path.push(node);
while(node != this._startNode)
{
node = node.parent;
this._path.unshift(node);
}
} public get path()
{
return this._path;
} //是否待检查
private isOpen(node:Node):boolean
{
for(var i = ; i < this._open.length; i++)
{
if(this._open[i] == node)
{
return true;
}
}
return false;
} //是否已检查
private isClosed(node:Node):boolean
{
for(var i = ; i < this._closed.length; i++)
{
if(this._closed[i] == node)
{
return true;
}
}
return false;
} //曼哈顿算法
private manhattan(node:Node)
{
return Math.abs(node.x - this._endNode.x) * this._straightCost + Math.abs(node.y + this._endNode.y) * this._straightCost;
} private euclidian(node:Node)
{
var dx = node.x - this._endNode.x;
var dy = node.y - this._endNode.y;
return Math.sqrt(dx * dx + dy * dy) * this._straightCost;
} private diagonal(node:Node)
{
var dx = Math.abs(node.x - this._endNode.x);
var dy = Math.abs(node.y - this._endNode.y);
var diag = Math.min(dx, dy);
var straight = dx + dy;
return this._diagCost * diag + this._straightCost * (straight - * diag);
} public get visited()
{
return this._closed.concat(this._open);
}
} }

Grid网格

/**
* 网格类
* @author chenkai
* @since 2017/11/3
*/
namespace astar{
export class Grid {
private _startNode:Node; //起点
private _endNode:Node; //终点
private _nodes:Array<any>; //Node数组
private _numCols:number; //网格行列
private _numRows:number; public constructor(numCols:number, numRows:number) {
this._numCols = numCols;
this._numRows = numRows;
this._nodes = []; for(let i:number=;i<numCols;i++){
this._nodes[i] = [];
for(let j:number=;j<numRows;j++){
this._nodes[i][j] = new Node(i,j);
}
}
} public getNode(x:number , y:number):Node{
return this._nodes[x][y];
} public setEndNode(x:number, y:number){
this._endNode = this._nodes[x][y];
} public setStartNode(x:number, y:number){
this._startNode = this._nodes[x][y];
} public setWalkable(x:number, y:number, value:boolean){
this._nodes[x][y].walkable = value;
} public get endNode(){
return this._endNode;
} public get numCols(){
return this._numCols;
} public get numRows(){
return this._numRows;
} public get startNode(){
return this._startNode;
}
}
}

Node节点

/**
* Node 节点
* @author chenkai
* @since 2017/11/3
*/
namespace astar{
export class Node {
public x:number; //列
public y:number; //行
public f:number; //代价 f = g+h
public g:number; //起点到当前点代价
public h:number; //当前点到终点估计代价
public walkable:boolean = true;
public parent:Node;
public costMultiplier:number = 1.0; public constructor(x:number , y:number) {
this.x = x;
this.y = y;
}
}
}

演示Demo

class Game extends egret.Sprite
{
private _cellSize:number = ;
private _grid:astar.Grid;
private _player:egret.Sprite;
private _index:number;
private _path:Array<any>; public constructor()
{
super();
this.makePlayer();
this.makeGrid();
this.addEventListener(egret.Event.ADDED_TO_STAGE, ()=>{
this.stage.addEventListener(egret.TouchEvent.TOUCH_TAP, this.onGridClick, this);
},this); } /**
* Creates the player sprite. Just a circle here.
*/
private makePlayer()
{
this._player = new egret.Sprite();
this._player.graphics.beginFill(0xff0000);
this._player.graphics.drawCircle(, , );
this._player.graphics.endFill();
this._player.x = Math.random() * ;
this._player.y = Math.random() * ;
this.addChild(this._player);
} /**
* Creates a grid with a bunch of random unwalkable nodes.
*/
private makeGrid():void
{
this._grid = new astar.Grid(,);
for(var i = ; i < ; i++)
{
this._grid.setWalkable(Math.floor(Math.random() * ),
Math.floor(Math.random() * ),
false);
}
this.drawGrid();
} /**
* Draws the given grid, coloring each cell according to its state.
*/
private drawGrid():void
{
this.graphics.clear();
for(let i = ; i < this._grid.numCols; i++)
{
for(let j = ; j <this._grid.numRows; j++)
{
var node:astar.Node =this._grid.getNode(i, j);
//这里有Bug, 绘制将近150次时, drawRect会出错
// this.graphics.lineStyle(0);
// this.graphics.beginFill(this.getColor(node));
// this.graphics.drawRect(i * this._cellSize, j * this._cellSize, this._cellSize, this._cellSize);
let sp:egret.Sprite = new egret.Sprite();
sp.graphics.beginFill(this.getColor(node));
sp.graphics.drawRect(,,,);
sp.graphics.endFill();
sp.x = i*this._cellSize;
sp.y = j*this._cellSize;
this.addChild(sp);
}
}
this.addChild(this._player);
} /**
* Determines the color of a given node based on its state.
*/
private getColor(node:astar.Node)
{
if(!node.walkable) return ;
if(node == this._grid.startNode) return 0xcccccc;
if(node == this._grid.endNode) return 0xcccccc;
return 0xffffff;
} /**
* Handles the click event on the GridView. Finds the clicked on cell and toggles its walkable state.
*/
private onGridClick(event:egret.TouchEvent):void
{
var xpos = Math.floor(event.stageX / this._cellSize);
var ypos = Math.floor(event.stageY / this._cellSize);
this._grid.setEndNode(xpos, ypos); xpos = Math.floor(this._player.x / this._cellSize);
ypos = Math.floor(this._player.y / this._cellSize);
this._grid.setStartNode(xpos, ypos); this.drawGrid(); this.startTime = egret.getTimer();
this.findPath();
console.log("耗时:", egret.getTimer() - this.startTime);
} private startTime = ; /**
* Creates an instance of AStar and uses it to find a path.
*/
private findPath():void
{
var aStar:astar.AStar = new astar.AStar();
if(aStar.findPath(this._grid))
{
this._path = aStar.path;
this._index = ;
this.addEventListener(egret.Event.ENTER_FRAME, this.onEnterFrame, this);
}
} /**
* Finds the next node on the path and eases to it.
*/
private onEnterFrame(event:egret.Event):void
{
var targetX = this._path[this._index].x * this._cellSize + this._cellSize / ;
var targetY = this._path[this._index].y * this._cellSize + this._cellSize / ;
var dx = targetX - this._player.x;
var dy = targetY - this._player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if(dist < )
{
this._index++;
if(this._index >= this._path.length)
{
this.removeEventListener(egret.Event.ENTER_FRAME, this.onEnterFrame, this);
}
}
else
{
this._player.x += dx * .;
this._player.y += dy * .;
}
}
}

AStar A* A星 算法TypeScript版本的更多相关文章

  1. Java开源-astar:A 星算法

    astar A星算法Java实现 一.适用场景 在一张地图中,绘制从起点移动到终点的最优路径,地图中会有障碍物,必须绕开障碍物. 二.算法思路 1. 回溯法得到路径 (如果有路径)采用“结点与结点的父 ...

  2. 算法起步之A星算法

    原文:算法起步之A星算法 用途: 寻找最短路径,优于bfs跟dfs 描述: 基本描述是,在深度优先搜索的基础上,增加了一个启发式算法,在选择节点的过程中,不是盲目选择,而是有目的的选的,F=G+H,f ...

  3. POJ 2449 Remmarguts' Date (SPFA + A星算法) - from lanshui_Yang

    题目大意:给你一个有向图,并给你三个数s.t 和 k ,让你求从点 s 到 点 t 的第 k 短的路径.如果第 k 短路不存在,则输出“-1” ,否则,输出第 k 短路的长度. 解题思路:这道题是一道 ...

  4. Cocos2d-x 3.1.1 学习日志16--A星算法(A*搜索算法)学问

    A *搜索算法称为A星算法.这是一个在图形平面,路径.求出最低通过成本的算法. 经常使用于游戏中的NPC的移动计算,或线上游戏的BOT的移动计算上. 首先:1.在Map地图中任取2个点,開始点和结束点 ...

  5. A*搜寻算法(A星算法)

    A*搜寻算法[编辑] 维基百科,自由的百科全书 本条目需要补充更多来源.(2015年6月30日) 请协助添加多方面可靠来源以改善这篇条目,无法查证的内容可能会被提出异议而移除. A*搜索算法,俗称A星 ...

  6. A星算法(Java实现)

    一.适用场景 在一张地图中.绘制从起点移动到终点的最优路径,地图中会有障碍物.必须绕开障碍物. 二.算法思路 1. 回溯法得到路径 (假设有路径)採用"结点与结点的父节点"的关系从 ...

  7. electron教程(番外篇二): 使用TypeScript版本的electron, VSCode调试TypeScript, TS版本的ESLint

    我的electron教程系列 electron教程(一): electron的安装和项目的创建 electron教程(番外篇一): 开发环境及插件, VSCode调试, ESLint + Google ...

  8. JAVA根据A星算法规划起点到终点二维坐标的最短路径

    工具类 AStarUtil.java import java.util.*; import java.util.stream.Collectors; /** * A星算法工具类 */ public c ...

  9. 基于HTML5的WebGL呈现A星算法3D可视化

    http://www.hightopo.com/demo/astar/astar.html 最近搞个游戏遇到最短路径的常规游戏问题,一时起兴基于HT for Web写了个A*算法的WebGL 3D呈现 ...

随机推荐

  1. 怎样编写socket套接字

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/ ...

  2. .NET操作Excel笔记

    如果你新建一个项目的话,首先要添加Microsoft.Office.Core 与Microsoft.Office.Interop.Exce这两个应用,然后就能很方便的操作了,示例代码(只实现了简单的读 ...

  3. CMM已经落伍了,敏捷才是王道

    首先强调一下,敏捷和有没有文档一点关系都没有.我只是对于CMM的那些文档感觉有些浪费. 看看那些文档,看看那些流程.想想那些伟大的软件作品,哪个是用CMM开发出来的? 作为测试工程师,程序员的你在CM ...

  4. 如何对抗、预防 SQL注入 攻击

    一.SQL注入简介 SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库. 二.SQL注入攻击的总体 ...

  5. relation 关联模型

    关联关系必然有一个参照表,例如:有一个员工档案管理系统项目,这个项目要包括下面的一些数据表:基本信息表.员工档案表.部门表.项目组表.银行卡表(用来记录员工的银行卡资料).这些数据表之间存在一定的关联 ...

  6. 全局结果集,带参数的结果集和动态结果集(struts2)

    全局结果集: 当许多action都有共同的结果时,如果每个package都存在一个相同结果,会使得struts.xml比较臃肿,所以使用全局的结果集.一个包内的全局结果集可以通过包的继承而被其它包使用 ...

  7. sqlldr导入数据(以PostgreSql>>>Oracle为例)

    1.在目标数据库中创建表 1.1点击源表,复制创建语句 1.2 修改数据类型以匹配目标数据库,如: 字符串类型:character varying(20)>>>varchar2(20 ...

  8. jquery-包裹元素

    1.wrap方法 在每个匹配的元素外层包上一个html元素 参数类型说明: 1)html字符串 $('p').wrap('<div></div>'); 传入的html标签也可以 ...

  9. DOTween中的Time.Scale

    因为在做游戏暂停的时候通常会使用Time.Scale = 0 ,可是暂停的时候UI如果需要继续有动画怎么办呢?在DoTween中只需要设置         tweener.SetUpdate(true ...

  10. html5 经验记录 持续更新

    1 关于page cache 由于移动端浏览器webkit基本都实现了page cache(火狐叫做back-forwoad cache);所以回退操作基本不会触发onload操作了,不过上一页的状态 ...