FLEXAS3做FlashGame地图寻路实例.docx

上传人:b****8 文档编号:11382383 上传时间:2023-02-28 格式:DOCX 页数:22 大小:154.85KB
下载 相关 举报
FLEXAS3做FlashGame地图寻路实例.docx_第1页
第1页 / 共22页
FLEXAS3做FlashGame地图寻路实例.docx_第2页
第2页 / 共22页
FLEXAS3做FlashGame地图寻路实例.docx_第3页
第3页 / 共22页
FLEXAS3做FlashGame地图寻路实例.docx_第4页
第4页 / 共22页
FLEXAS3做FlashGame地图寻路实例.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

FLEXAS3做FlashGame地图寻路实例.docx

《FLEXAS3做FlashGame地图寻路实例.docx》由会员分享,可在线阅读,更多相关《FLEXAS3做FlashGame地图寻路实例.docx(22页珍藏版)》请在冰豆网上搜索。

FLEXAS3做FlashGame地图寻路实例.docx

FLEXAS3做FlashGame地图寻路实例

FLEXAS3做FlashGame地图寻路实例

1.总结目的

在地图中,通过鼠标或者由程序自动运行,让一个人物自动从地图的一点走到另一点。

需要计算两点之间的最优路线,要实现这样的寻路算法。

最常规和最简单的方法,使用A*算法。

本篇总结不具体讲解A*算法的实现以及原理,主要告诉怎么用。

后面的总结中我会陆续把A*算法进行详细分析,希望大家学习。

2.开发流程

2.1.地图加载

1)在寻路过程中,地图是被分为若干个小格子,当然,根据格子数量的不同,路线长度的不同,计算寻路的时间也就不同。

上面是有一个由20*20的地图拼起来的地图,每一个地图块是有20像素*20像素元件做成。

每一个地图块是2帧构成,地图帧是人物可以行走的路线,第二帧是障碍物(桌子)。

上面的地图是路线和障碍物8比2的概率生成,参考代码:

Block是地图块元件类。

用Flashcs3已经做好。

this.mass_x_count是指地图X轴上板块数量

this.mass_y_count是指地图Y轴上板块数量

distancex是指地图X轴离边界Left的距离

distancey是指地图Y轴离边界Top的距离

aNodeMap是一个2维数组,记录着每一个地图块当前的状态,是障碍物还是路线。

地图初始化中,根据两个For循环嵌套,生成一个表格状的地图。

这里我不在详细介绍,详细会AS3的一定可以看的懂。

2.2.地图上移动人物加载

1)路线寻路肯定要有一个元件在地图上移动,才可以正确的显示出寻路的过程。

无论是一个人物移动或多个人物移动,基本做法相同,下面我们就来加载一个人物物件到地图上来。

Waiter是一个移动的任务元件。

在这里我们叫“服务员元件”

Timer是为服务员增加一个timer事件,主要目的是为了服务员从一个地图块移动到另一个地图块,不是跳过去的,而是慢慢的移动过去的。

此方法主要在加载完地图后调用,指定人物加载的X,Y坐标,进行加载。

2.3.选择移动目的地

1)地图和服务员加载完成后,我们需要选择服务员移动的目的地,选择的方式有很多。

举个例子,人人餐厅中客人进来就餐,首先进门后,程序会自动寻找有空位的X,Y坐标,然后计算路线,客人就会沿着路线走进去。

同样服务员也会根据客人进来餐厅的循序,以及客人所做的座椅的坐标进行计算路线,然后走过去服务。

2)由于我们只是一个例子,所以就有我们鼠标确定目的地。

this.addEventListener(MouseEvent.CLICK,clickWay);

这个事件通过,用户鼠标点击地图上路线进行调用。

2.4.路线寻找,人物移动

1)在地图增加完后我们增加一个A*算法实例

AStar是A*算法的一个封装类。

我们需要把我们地图上路线和障碍物二维数组传递给算法。

这个是在地图加载后完成

2)确定移动目的地后计算路线

上面代码是在选择目的地后补充的代码

设置A*(asrar)算法的其实点和目的地。

起始点和目的地封装成ANode对象给算法的。

ANode是一个算法计算中节点的保存,记录着节点的位置X,Y,节点ID,以及使用曼哈顿方法计算F=G+HF、G、H值的保存。

从而做为路线计算中开启列表进行存储。

最后会调用DoSearch判断路线的获取是否成功。

获取的路线调用astar.aPath方法进行获取。

启动timer进行服务员移动操作。

3)服务员移动

在移动服务之前,我们确定,我们寻找到路线,此服务员的上一个路线已经完成。

代码如下:

这个方法是在寻找到路线后,timer启动执行的。

bMove表示是否移动服务员。

player代表当前移动中的服务员对象,他是在创建服务员的时候保存在全局变量中。

A*算法会在下面参考代码中会有

3.参考代码

A*寻路算法代码:

importflash.geom.Point;

/*

*A*寻路算法

*@authorliujia

*@version1.0

*/

publicclassAStar{

//垂直或水平移动一格的代价

privateconstCOST_STRAIGHT:

int=10;

//斜向移动一格的代价

privateconstCOST_DIAGONAL:

int=14;

//起始节点ANode

publicvarndStart:

ANode;

//目标节点ANode

publicvarndEnd:

ANode;

//当前节点ANode

publicvarndCurrent:

ANode;

//最大寻路步数限制

privatevarnMaxTry:

int;

//尝试次数计数器

privatevarnCrtTry:

int;

//开放表,元素为ANode类型

privatevaraOpenList:

Array;

//关闭表,元素为ANode类型

privatevaraCloseList:

Array;

//八个方向数组,从节点正上方开始,顺时针排列

privateconstaDir:

Array=[[0,-1],[1,-1],[1,0],[1,1],[0,1],[-1,1],[-1,0],[-1,-1]];

//地图节点数组

publicvaraNodeMap:

Array=[];

//地图大小

publicvarmapwidth:

int;

publicvarmapheight:

int;

//记录节点在aOpenList数组的位置

privatevarnum:

int;

//路径数组

publicvaraPath:

Array;

//是否找到路径

publicvarbPathFind:

Boolean;

//构造函数

publicfunctionAStar(amap:

Array){

nMaxTry=600;

nCrtTry=0;

Init();

mapwidth=amap[0].length;

mapheight=amap.length;

aNodeMap=amap;

}

//初始化

publicfunctionInit():

void{

bPathFind=false;

aOpenList=[];

aCloseList=[];

aPath=[];

}

//添加到open表

publicfunctionaddFirstOpen():

void{

aOpenList.push(ndStart);

}

//取得指定点周围可通过的点,从正上方开始

privatefunctionGetRound(apos:

Array):

Array{

vararr:

Array=newArray();

for(vari:

int=0;i

varxp=apos[0]+aDir[i][0];

varyp=apos[1]+aDir[i][1];

if(IsOutRange([xp,yp])||IsStart([xp,yp])||!

IsPass([xp,yp])||IsCorner([xp,yp])||IsInClose([xp,yp]))

continue

arr.push([xp,yp]);

}

returnarr;

}

//是否超出地图范围

privatefunctionIsOutRange(apos:

Array):

Boolean{

if(apos[0]<0||apos[0]>=mapwidth||apos[1]<0||apos[1]>=mapheight)

returntrue;

returnfalse;

}

//是否是起点

privatefunctionIsStart(apos:

Array):

Boolean{

if(apos[0]==ndStart.pos[0]&&apos[1]==ndStart.pos[1])

returntrue;

returnfalse;

}

//是否可以通过

privatefunctionIsPass(apos:

Array):

Boolean{

if(IsOutRange(apos)){

returnfalse;

}else{

return(aNodeMap[apos[1]][apos[0]]>0?

false:

true);

}

}

//是否是拐角

privatefunctionIsCorner(apos:

Array):

Boolean{

if(IsPass(apos)){

if(apos[0]>ndCurrent.pos[0]){

if(apos[1]>ndCurrent.pos[1]){

if(!

IsPass([apos[0]-1,apos[1]])||!

IsPass([apos[0],apos[1]-1]))

returntrue;

}

elseif(apos[1]

if(!

IsPass([apos[0]-1,apos[1]])||!

IsPass([apos[0],apos[1]+1]))

returntrue;

}

}

elseif(apos[0]

if(apos[1]>ndCurrent.pos[1]){

if(!

IsPass([apos[0]+1,apos[1]])||!

IsPass([apos[0],apos[1]-1]))

returntrue;

}

elseif(apos[1]

if(!

IsPass([apos[0]+1,apos[1]])||!

IsPass([apos[0],apos[1]+1]))

returntrue;

}

}

}

returnfalse;

}

//是否在开启列表中

//获得传入参数在aOpenlist数组的位置,如不存在返回false,存在为true,位置索引保存到变量num中。

privatefunctionIsInOpen(apos:

Array):

Boolean{

varbool:

Boolean=false;

varid=apos[1]*mapwidth+apos[0];

for(vari=0;i

if(aOpenList[i].id==id){

bool=true;

num=i;

break;

}

}

returnbool;

}

//是否在关闭列表中

privatefunctionIsInClose(apos:

Array):

Boolean{

varbool:

Boolean=false;

varid=apos[1]*mapwidth+apos[0];

for(vari=0;i

if(aCloseList[i].id==id){

bool=true;

break;

}

}

returnbool;

}

//取得F值,参数为某一节点周围的节点

privatefunctionGetF(around:

Array):

void{

//F,综合的距离值;

//H,给定节点到目标点的距离值;

//G,起点到给定节点的距离值

varF:

int,H:

int,G:

int;

varapos:

Array;

for(vari:

int=0;i

apos=around[i];

//是否与起点在同一直线上

if(apos[0]==ndStart.pos[0]||apos[1]==ndStart.pos[1]){

G=ndCurrent.G+COST_STRAIGHT;

}else{

G=ndCurrent.G+COST_DIAGONAL;

}

//如果当前点已存在aOpenlist数组中

if(IsInOpen(apos)){

varopos:

ANode=aOpenList[num]asANode;

//如果当前点G值更小,更改父节点

if(G

opos.F=G+opos.H;

opos.G=G;

opos.pid=ndCurrent.id;

}else{

G=opos.G;

}

}

//否则将当前点添加到aOpenList数组

else{

H=(Math.abs(ndEnd.pos[0]-apos[0])+Math.abs(ndEnd.pos[1]-apos[1]))*COST_STRAIGHT;

F=G+H;

varnewnode:

ANode=newANode(apos,apos[1]*mapwidth+apos[0],0,ndCurrent.id);

newnode.F=F;

newnode.G=G;

newnode.H=H;

aOpenList.push(newnode);

}

}

}

//搜索路径

publicfunctionDoSearch():

Boolean{

aOpenList=[];

aCloseList=[];

addFirstOpen();

while(aOpenList.length){

nCrtTry++;

//如果超出寻路步数限制

if(nCrtTry>nMaxTry){

destroyData();

returnfalse;

}

GetF(GetRound(ndCurrent.pos));

//按照F值由大到小的顺序排列开启列表

aOpenList.sortOn("F",Array.NUMERIC|Array.DESCENDING);

//将开启列表最后一位元素列入关闭列表

varlastNode:

ANode=aOpenList[aOpenList.length-1];

aCloseList.push(lastNode);

ndCurrent=lastNode;

if(aOpenList.length>1)

aOpenList.pop();

//如果当前节点是目标节点,路径找到,返回true

if(ndCurrent.id==ndEnd.id){

aPath=GetPath();

destroyData();

bPathFind=true;

ndStart=ndCurrent;

returntrue;

}

}

bPathFind=false;

destroyData();

aPath=[];

returnfalse;

}

//清空各数组

privatefunctiondestroyData():

void{

aOpenList=[];

aCloseList=[];

nCrtTry=0;

}

//取得路径数组

privatefunctionGetPath():

Array{

varapath:

Array=[];

vartmpnode:

ANode=aCloseList[aCloseList.length-1]asANode;

apath.push(tmpnode.pos);

varinc:

int=0;

while(inc<=aCloseList.length){

inc++

for(vari:

int=0;i

if(aCloseList[i].id==tmpnode.pid){

tmpnode=aCloseList[i];

apath.push(tmpnode.pos)

}

if(tmpnode.id==ndStart.id)

break;

}

}

returnapath;

}

}

ANode节点对象:

publicclassANodeextendsObject{

publicvarpid:

int;

publicvarid:

int;

publicvarpos:

Array;

publicvarG:

int;

publicvarH:

int;

publicvarF:

int;

publicvarblock:

int;//1isblock,0ispass

publicfunctionANode(_pos:

Array,_id:

int,_block:

int=0,_pid:

int=0){

id=_id;

pid=_pid;

pos=_pos;

block=_block;

G=0;

H=0;

F=0;

}

}

寻路实例主类:

importflash.events.Event;

importflash.events.MouseEvent;

importflash.events.TimerEvent;

importflash.utils.Timer;

importmx.containers.Canvas;

importmx.controls.Alert;

publicclassSceneMainextendsCanvas

{

//地板离地图的边距

privatevardistancex:

int=30;

privatevardistancey:

int=30;

//地板的默认宽度和高度

privatevarfloorw:

int=20;

privatevarfloorh:

int=20;

//地板块数量

privatevarmass_x_count:

int;

privatevarmass_y_count:

int;

//服务员行走速度

privatevarinterval:

int=50;

//A*算法实例

privatevarastar:

AStar;

//移动属性

privatevarbMove:

Boolean;

//路径数组

privatevaraPath:

Array;

//路径数组指针

privatevarpathpoint:

int;

//地图数组

privatevaraNodeMap:

Array;

//服务员对象

privatevarplayer:

Waiter=null;

//服务员沿路线行走timer

privatevartimer:

Timer=newTimer(interval);

publicfunctionSceneMain(x:

int,y:

int)

{

aNodeMap=newArray();

this.mass_x_count=x;

this.mass_y_count=y;

//初始化地图

this.initScene();

//初始化移动服务员

this.loadMoveRen(distancey,distancex);

this.addEventListener(MouseEvent.CLICK,clickWay);

}

/**

*初始化地图

*/

publicfunctioninitScene():

void{

varblock:

Block=newBlock();

this.width=block.width*this.mass_x_count+distancey;

this.height=block.height*this.mass_y_count+distancex;

for(vari:

int=0;i

aNodeMap[i]=newArray();

for(varj:

int=0;j

varblock1:

Block=newBlock();

if(i==0&&j==0){

block1.gotoAndStop

(1);

}else{

vargailu:

Number=Math.floor(Math.random()*10)+1;

block1.go

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 国外设计风格

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1