对上一篇小怪系列文章作详细分析,帮助大家理解。
正文
首先,对于曼哈顿估价法。
你就可以理解为直线的一段或者几段距离的加和,直线距离。

// 曼哈顿估价法,传入当前点与目标点,返回估值
// abs 为取绝对值manHattan (nowPoint, pIndex) {let dx = Math.abs(nowPoint.x - pIndex.x);let dy = Math.abs(nowPoint.y - pIndex.y);return dx + dy;}

然后让我们分析一下路径上点的对象应该具有的信息。

// new 一个空对象
let obj = new Object();
// 每个网格的点的行和列 对应 x 和 y
obj.x = v.x;
obj.y = v.y;
obj.g = this.manHattan(v, this.mIndex);
obj.h = this.manHattan(v, this.pIndex);
// g 为从起点,沿着路径,移动到当前点的移动耗费。
// h 为从当前点到终点的移动耗费。这不包括障碍,单纯的是曼哈顿距离,也就是直线距离。因为我们不知道什么时候有障碍,这叫启发式。
// 我们的路径是通过反复遍历 open 列表并且选择具有最低 f 值装入 close 列表。因为 f 是综合值,调整 g 和 h 的比例会起到不同寻路效果。
obj.f = obj.g + obj.h;
// 起点无上级,然后搜索到目标点后可以轻易的靠着 parent 回溯到起点。
obj.parent = parent;

按步演示

在 start 中声明数据。

start () {// 小怪的坐标,起点this.mIndex = cc.v2(4, 0);// 玩家坐标点,终点this.pIndex = cc.v2(3, 9);// 开始this.aStar();},

限制 500 次很好理解,每一次循环 time-- 这样可以防止找不到路径造成卡死。
然后让我们为起点建立对象。然后放入 close 列表中。
close 列表装的是那些已经搜索过的点,open 列表中放入待选择的点,然后在 open 列表中选择 f 值较低的点,放入 close 中,完成一轮搜索。直到我们找到终点。

 aStar () {// 限制次数 500;// 首先将小怪的位置装入 close 列表let time = 500;let obj = new Object();obj.x = this.mIndex.x;obj.y = this.mIndex.y;obj.g = this.manHattan(this.mIndex, this.mIndex);obj.h = this.manHattan(this.mIndex, this.pIndex);obj.f = obj.g + obj.h;obj.parent = null;// 将起点放入this.pushInClose(obj);// ......}pushInClose (obj) {this.close.push(obj);},

图示

我们从起点开始,寻找当前点的周围一圈,然后计算 g h 得到 f 值。

while (true) {time--;// 周围一圈装入 openthis.aroundPos(temp);// 在 open 中找到 f 最小的,装入 close 并返回该点;temp = this.findMinInOpen();if (temp.x == this.pIndex.x && temp.y == this.pIndex.y) {// 到达目的地break;}if (time <= 0) {console.log('寻找不到');break;}
}

向四周寻找

aroundPos (parent) {// 上下左右四个方向let dir = [[0,1],[1,0],[0,-1],[-1,0]];for (let i = 0; i < 4;i++) {let mx = parent.x + dir[i][0];let my = parent.y + dir[i][1];// 是否出界if (mx < 0 || mx > 6 || my < 0 || my > 9) {continue;}// 是否为墙if (this.map[mx][my] == 1) {continue;}// 是否已经在 close 中了if (this.isInClose(mx, my)) {continue;}// 是否已经在 close 中了if (this.isInOpen(mx, my)) {continue;}// 装入 openthis.pushInOpen(cc.v2(mx, my), parent);}
},
findMinInOpen () {let min = 999;let index = null;// 找到 open 中最小的 f 的点的下标for (let i = 0; i < this.open.length; i++) {if (this.open[i].f <= min) {min = this.open[i].f;index = i;}}// 运用 splice 将 f 最小的点切出来let obj = this.open.splice(index, 1);// 放入 close 列表并返回this.pushInClose(obj[0]);return obj[0];
},

放入 close 列表方法是直接放入 close 数组,而 open 列表需要我们创建点的信息,因为是新的点。

pushInOpen (v, parent) {let obj = new Object();obj.x = v.x;obj.y = v.y;obj.g = this.manHattan(v, this.mIndex);obj.h = this.manHattan(v, this.pIndex);obj.f = obj.g + obj.h;obj.parent = parent;this.open.push(obj);
},

判断是否在 open close 两个列表里就是 for 循环

isInOpen (mx, my) {for (let i = 0; i < this.open.length; i++) {if (this.open[i].x == mx && this.open[i].y == my) {return true;}}return false;
},
isInClose (mx, my) {for (let i = 0; i < this.close.length; i++) {if (this.close[i].x == mx && this.close[i].y == my) {return true;}}return false;
},

最后我们发现
在 close 列表里是很多发现的点,数组的最后一定是目标点。

在 close 数组的最后就是目标点,我们只要根据目标点,进行不断的向上访问 parent 就能回溯到起点。

代码实现

// 根据 parent 最终确认路线
let l = this.close.length - 1;
let p = this.close[l];
this.final = [];
while(p) {this.final.push(p);p = p.parent;
}
// 将 close 中的正确路线装入 final 后其实是反序的
// 翻转
this.final.reverse();
// 沿着 final 走
this.go(0);

沿着路径走就很简单了,利用 runAction不断的走,直到走完

go (i) {this.me.runAction(cc.sequence(cc.moveTo(0.5,this.convertToPoints(this.final[i].x, this.final[i].y)),cc.callFunc(() => {if (i == this.final.length - 1) return;i++;this.go(i);},this)));
},

行列坐标与实际坐标转化

// 转化坐标
convertToPoints (dx, dy) {let y = 300 - 100 * dx;let x = 100 * dy - 450;return cc.v2(x, y);
},

好了,不知小伙伴们这回看明白没有!
O(∩_∩)O~~

CocosCreator之KUOKUO趣味文章:小怪A星寻路详解相关推荐

  1. CocosCreator之KUOKUO趣味文章:小怪要绕墙 3

    引擎版本 v2.0.8 恢复视野 继续故事,小怪在黑夜中失去了视野.它找不到玩家的位置,只好自己在默默的思考,开发自己大脑. 渐渐地,小怪可以每秒钟思考两次了. properties: {thinkC ...

  2. CocosCreator之KUOKUO趣味文章:小怪的诞生 1

    引擎版本 v2.0.8 小怪的诞生 这,本该是一片虚无之地. 却有一个 960*640 的神秘领域降临(Canvas): 这,本该是一块荒凉之所. 却有一个玩家凭空产生(player节点)... 咦! ...

  3. CocosCreator之KUOKUO趣味文章:小怪会勘探 4

    引擎版本 v2.0.9 小怪的思考 在上一篇文章中,小怪采用了用脸摩擦墙的方法,成功越过障碍,抓到玩家.目的是实现了,但是小怪认为,这是及其不雅观的. 于是它在夜黑风高之时,偷偷的勘探了地形,并描绘了 ...

  4. CocosCreator之KUOKUO趣味文章:小怪的视野 2

    引擎版本 v2.0.8 小怪的视野 正在小怪开心的追着玩家时,忽然飘起了雾.由于小怪的速度比玩家慢那么一点点,渐渐地,它看不见玩家了. 不得已.小怪停下了!它在思考!!! 代码模拟黑暗灯光效果 这里巧 ...

  5. 智能车视觉处理系列文章——迷宫巡线法详解(含代码)

    巡线方法 1.迷宫巡线法 ​ 按照上海交通大学的方法,通过使用迷宫巡线(种子生长法)在巡线的过程中进行图象的自适应阈值,这样可极大的减少计算量.具体思想参考上交文章,以下内容为对代码(以左手迷宫巡线为 ...

  6. access month函数用法_【Access文章】日期常用函数详解

    时 间:2015-08-20 09:46:13 作 者:摘 要: weekday 函数,WeekdayName函数(VBA),DateSerial 函数,DatePart函数 ,DateAdd 函数  ...

  7. 路径规划: a star, A星算法详解

    如此好贴,不能不转!原文地址:http://dev.gameres.com/Program/Abstract/Arithmetic/AmitAStar.mht 本文版权归原作者.译者所有,我只是转贴: ...

  8. 前向星和链式前向星(详解+模板)

    前向星和链式前向星 参考博客:深度理解链式前向星 什么是前向星 前向星是一种特殊的边集数组,我们把边集数组中的每一条边按照起点从小到大排序,如果起点相同就按照终点从小到大排序,并记录下以某个点为起点的 ...

  9. 微信公众号文章搜索接口9大详解

    微信公众号作为一个重要的自媒体平台,越来越受到人们的关注.而对于那些想要提高自己公众号文章点击率的人来说,微信公众号文章搜索接口是一个不可或缺的工具.本文将从以下9个方面详细介绍微信公众号文章搜索接口 ...

最新文章

  1. 物联网6类技术无线连接技术的分析
  2. nyoj 题目5 Binary String Matching
  3. 信号完整性分析大作业_Matplotlib数据可视化 amp; Pandas数据分析 综合实训大作业...
  4. 在C#中,当您在null对象上调用扩展方法时会发生什么?
  5. scala 函数定义
  6. debian7 安装配置
  7. 计算机主板过热报警,利用电脑主板BIOS的报警声音辨别电脑故障
  8. 面试:如何评价程序员
  9. 提升手机麦克风音量_安卓手机音量调整办法(听筒、话筒、扬声器)
  10. 诞生11年,入华9年,今年的智慧城市会更好吗?
  11. php主机卫士,Bypass360主机卫士SQL注入防御八种姿势
  12. simulink AWGN信道使用要点
  13. 信息系统项目管理师(第1章)
  14. chm格式电子书另类反编译法:使用压缩软件7Z简单实现CHM电子书反编译 | 志文工作室
  15. 9ku音乐网音乐爬取,仅供交流~~
  16. 安装 CentOS Ubuntu
  17. 人工智能会破灭嘛?听听福布斯邀请的这50位大拿怎么说
  18. C++程序方法 --- 病毒感染检测
  19. 有效前沿,CAMP, CAL, SML
  20. 图片如何缩小不降低清晰度?

热门文章

  1. 常见算法-孩子们的游戏
  2. Spring Cloud Alibaba实现服务的无损下线功能
  3. Android仿微信自定义字母导航栏
  4. mongodb之 mongodump 与 mongorestore
  5. Azkaban启动服务完成后浏览器访问8443端口出错
  6. 用python实现简单的队列
  7. 祝贺你成年了(python)
  8. KEIL的分散加载文件
  9. Tomcat 应用企业级优化
  10. vue-cli3.0 使用px2rem 或 postcss-plugin-px2rem