设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 4554|回复: 8
打印 上一主题 下一主题

[有事请教] 关于自动寻路的问题

[复制链接]

Lv1.梦旅人

梦石
0
星屑
220
在线时间
45 小时
注册时间
2019-10-1
帖子
35
跳转到指定楼层
1
发表于 2019-10-4 13:28:27 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
让事件接近主角使用的应该是类似于鼠标点击的自动寻路,但是会卡住,像下图这样

按照论坛大佬的说法,把Game_Character.prototype.searchLimi的限制数12放大就可以了,但是放大到30以后仍然会卡住

于是找到了17年的帖子,一个大佬写的脚本
JAVASCRIPT 代码复制
  1. /*:
  2.  * @plugindesc Character. v1.0.0
  3.  * @author Kong Jing
  4.  *
  5.  * @help
  6.  * 修复了自带的接近玩家(不会被障碍物卡主不动)
  7.  *
  8.  * 在自定义路线中写脚本
  9.  * this.moveTowardCharacterEx(index);
  10.  * 向着事件Id为index的坐标走去。
  11.  *
  12.  * this.moveTowardDestination(x, y);
  13.  * 向地图指定位置走去。
  14.  *
  15.  * this.moveTowardDestinationEx(Id1, Id2);
  16.  * 向变量Id1为x坐标, 变量Id2为y坐标的位置走去。
  17.  *
  18.  */
  19.  
  20. //原版本的一个细节问题2333.
  21. Game_Character.prototype.findDirectionTo = function(goalX, goalY) {
  22.     var searchLimit = this.searchLimit();
  23.     var mapWidth = $gameMap.width();
  24.     var nodeList = [];
  25.     var openList = [];
  26.     var closedList = [];
  27.     var start = {};
  28.     var best = null;//此处应该为null,原版本为start
  29.  
  30.     if (this.x === goalX && this.y === goalY) {
  31.         return 0;
  32.     }
  33.  
  34.     start.parent = null;
  35.     start.x = this.x;
  36.     start.y = this.y;
  37.     start.g = 0;
  38.     start.f = $gameMap.distance(start.x, start.y, goalX, goalY);
  39.     nodeList.push(start);
  40.     openList.push(start.y * mapWidth + start.x);
  41.  
  42.         if(start.f == 1){
  43.                 var deltaX1 = $gameMap.deltaX(goalX, start.x);
  44.                 var deltaY1 = $gameMap.deltaY(goalY, start.y);
  45.                 if (deltaY1 > 0 && this.isMapPassable(start.x, start.y, 2)) {
  46.                         return 2;
  47.                 } else if (deltaX1 < 0 && this.isMapPassable(start.x, start.y, 4)) {
  48.                         return 4;
  49.                 } else if (deltaX1 > 0 && this.isMapPassable(start.x, start.y, 6)) {
  50.                         return 6;
  51.                 } else if (deltaY1 < 0 && this.isMapPassable(start.x, start.y, 8)) {
  52.                         return 8;
  53.                 }
  54.         }
  55.     while (nodeList.length > 0) {
  56.         var bestIndex = 0;
  57.         for (var i = 0; i < nodeList.length; i++) {
  58.             if (nodeList[i].f < nodeList[bestIndex].f) {
  59.                 bestIndex = i;
  60.             }
  61.         }
  62.  
  63.         var current = nodeList[bestIndex];
  64.         var x1 = current.x;
  65.         var y1 = current.y;
  66.         var pos1 = y1 * mapWidth + x1;
  67.         var g1 = current.g;
  68.  
  69.         nodeList.splice(bestIndex, 1);
  70.         openList.splice(openList.indexOf(pos1), 1);
  71.         closedList.push(pos1);
  72.  
  73.         if (current.x === goalX && current.y === goalY) {
  74.             best = current;
  75.             goaled = true;
  76.             break;
  77.         }
  78.  
  79.         if (g1 >= searchLimit) {
  80.             continue;
  81.         }
  82.  
  83.         for (var j = 0; j < 4; j++) {
  84.             var direction = 2 + j * 2;
  85.             var x2 = $gameMap.roundXWithDirection(x1, direction);
  86.             var y2 = $gameMap.roundYWithDirection(y1, direction);
  87.             var pos2 = y2 * mapWidth + x2;
  88.  
  89.             if (closedList.contains(pos2)) {
  90.                 continue;
  91.             }
  92.             if (!this.canPass(x1, y1, direction)) {
  93.                 continue;
  94.             }
  95.  
  96.             var g2 = g1 + 1;
  97.             var index2 = openList.indexOf(pos2);
  98.  
  99.             if (index2 < 0 || g2 < nodeList[index2].g) {
  100.                 var neighbor;
  101.                 if (index2 >= 0) {
  102.                     neighbor = nodeList[index2];
  103.                 } else {
  104.                     neighbor = {};
  105.                     nodeList.push(neighbor);
  106.                     openList.push(pos2);
  107.                 }
  108.                 neighbor.parent = current;
  109.                 neighbor.x = x2;
  110.                 neighbor.y = y2;
  111.                 neighbor.g = g2;
  112.                 neighbor.f = g2 + $gameMap.distance(x2, y2, goalX, goalY);
  113.                 if (!best || neighbor.f - neighbor.g < best.f - best.g) {
  114.                     best = neighbor;
  115.                 }
  116.             }
  117.         }
  118.     }
  119.  
  120.     var node = best;
  121.     while (node.parent && node.parent !== start) {
  122.         node = node.parent;
  123.     }
  124.  
  125.     var deltaX1 = $gameMap.deltaX(node.x, start.x);
  126.     var deltaY1 = $gameMap.deltaY(node.y, start.y);
  127.     if (deltaY1 > 0) {
  128.         return 2;
  129.     } else if (deltaX1 < 0) {
  130.         return 4;
  131.     } else if (deltaX1 > 0) {
  132.         return 6;
  133.     } else if (deltaY1 < 0) {
  134.         return 8;
  135.     }
  136.  
  137.     var deltaX2 = this.deltaXFrom(goalX);
  138.     var deltaY2 = this.deltaYFrom(goalY);
  139.     if (Math.abs(deltaX2) > Math.abs(deltaY2)) {
  140.         return deltaX2 > 0 ? 4 : 6;
  141.     } else if (deltaY2 !== 0) {
  142.         return deltaY2 > 0 ? 8 : 2;
  143.     }
  144.  
  145.     return 0;
  146. };
  147. //优化接近玩家
  148. Game_Character.prototype.moveTowardCharacter = function(character) {
  149.         var x = character.x;
  150.         var y = character.y;
  151.         var direction = this.findDirectionTo(x, y);
  152.         if (direction > 0) {
  153.                 this.moveStraight(direction);
  154.         }
  155. };
  156.  
  157. //向事件寻路
  158. Game_Character.prototype.moveTowardCharacterEx = function(index) {
  159.         var character = $gameMap._events[index];
  160.         var x = character.x;
  161.         var y = character.y;
  162.         var direction = this.findDirectionTo(x, y);
  163.         if (direction > 0) {
  164.                 this.moveStraight(direction);
  165.         }
  166. };
  167.  
  168. //向指定坐标寻路
  169. Game_Character.prototype.moveTowardDestination = function(x, y) {
  170.         var direction = this.findDirectionTo(x, y);
  171.         if (direction > 0) {
  172.                 this.moveStraight(direction);
  173.         }
  174. };
  175.  
  176. //向变量所指位置走去
  177. Game_Character.prototype.moveTowardDestinationEx = function(Id1, Id2) {
  178.         var x = $gameVariables.value(Id1);
  179.         var y = $gameVariables.value(Id2);
  180.         var direction = this.findDirectionTo(x, y);
  181.         if (direction > 0) {
  182.                 this.moveStraight(direction);
  183.         }
  184. };

使用后确实让“接近主角”不会卡主了,但是偶尔会报错,提示:cannot read property "parent" of null ,应该是这个脚本引起的问题,不是进入游戏触发寻路后立刻报错,而是走着走着不知什么时候会报错

想请问如何解决,或者有没有其他寻路脚本,谢谢各位大佬,国庆快乐

hfc.jpg (34.83 KB, 下载次数: 10)

hfc.jpg

Lv4.逐梦者

梦石
0
星屑
12157
在线时间
4435 小时
注册时间
2014-4-11
帖子
5955

开拓者

8
发表于 2019-10-6 20:14:14 | 只看该作者
本帖最后由 yang1zhi 于 2019-10-6 20:15 编辑

30不够就再加大。
距离越大,路线就越多的。
他要一个个路线试过来。
这东西,很耗资源的。

另外
这个寻路不是(接近主角)
接近主角,就是最短距离直接过来
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
220
在线时间
45 小时
注册时间
2019-10-1
帖子
35
7
 楼主| 发表于 2019-10-5 20:00:05 | 只看该作者
白嫩白嫩的 发表于 2019-10-5 18:22
yep_moveRouteCore插件 可以指定走到某个坐标或者事件或者角色 跳到某个坐标事件或者角色

JUMP TO: x, y

感谢大佬,这个yep之前试验过,关于一楼那个插件,我发现用事件替代玩家就不会报错了,虽然有点蠢但问题还是顺利解决了
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
3750
在线时间
1177 小时
注册时间
2016-8-9
帖子
2395

开拓者

6
发表于 2019-10-5 18:22:32 | 只看该作者
yep_moveRouteCore插件 可以指定走到某个坐标或者事件或者角色 跳到某个坐标事件或者角色

JUMP TO: x, y
JUMP TO: EVENT x
JUMP TO: PLAYER

MOVE TO: x, y
MOVE TO: EVENT x
MOVE TO: PLAYER

Example: Move To: 20, 30
         Move To: Event 5
         Move To: Player
         Avoid Move To: 30, 40
         Crash Move To: 40, 50


除此之外还有其他功能,寻路已经试验了,穿梭于各种npc事件中毫无压力
酸酸甜甜就④哇噢
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
220
在线时间
45 小时
注册时间
2019-10-1
帖子
35
5
 楼主| 发表于 2019-10-4 17:55:06 | 只看该作者
xjzsq 发表于 2019-10-4 15:09
我试了一下上面的脚本,使用上面的插件后只会让人物在无法搜到到达NPC所在路径的情况下反复在两个格乱晃, ...

谢谢大佬,一张17*13的小地图全部可通行没有障碍,但是有很多NPC,每次随机让一个NPC在随机移动N步后停下,循环这个过程。用了很多并行事件和随机数,不知道是不是这个原因产生了BUG。我用的MV跟着steam更新到1.6.2,
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
220
在线时间
45 小时
注册时间
2019-10-1
帖子
35
4
 楼主| 发表于 2019-10-4 17:45:29 | 只看该作者
wabcmcc 发表于 2019-10-4 15:26
RM官方論壇智能尋路簡單好用.
作者:Shaz

抱歉大佬我没有看懂,使用的时候让本事件移动到事件7处,是在移动路线里写脚本SmartPath event0 event7吗

点评

加上說明  发表于 2019-10-4 20:06
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
16059
在线时间
3993 小时
注册时间
2015-9-14
帖子
1337

开拓者

3
发表于 2019-10-4 15:26:37 | 只看该作者
本帖最后由 wabcmcc 于 2019-10-4 20:05 编辑

RM官方論壇智能尋路簡單好用.
作者:Shaz

事件頁,第三頁,插件命令.

插件命令:
  SmartPath eventId1 eventId2  //使事件1找到事件2的路徑  
     例子: SmartPath 1 2
  SmartPath eventId x y            //使事件找到位置x,y的路徑
  SmartPath eventId cancel       //取消尋找事件的路徑
.....................................
event = number for specific event    //事件= 特定事件的號碼.
event = 0 for "this" event               //事件= 0當前事件的號碼.
event = $gameVariables.value(x) to get the event id from variable x
//事件 = 從變量x中獲取事件ID
x, y = coordinates or $gameVariables.value(#) to use a variable coordinate
//x,y =坐標或以使用變量坐標


  1. //=============================================================================
  2. // Smart Pathfinding
  3. // by Shaz
  4. // Last Updated: 2015.10.21
  5. //=============================================================================

  6. /*:
  7. * @plugindesc Allows events or players to do smart Pathfinding
  8. * @author Shaz
  9. *
  10. * @help
  11. *
  12. * Plugin Command:
  13. *  SmartPath eventId1 eventId2      # Makes event 1 find path to event 2
  14. *  SmartPath eventId x y            # Makes event find a path to location x, y
  15. *  SmartPath eventId cancel         # Cancel Pathfinding for event
  16. *
  17. *  event = number for specific event
  18. *  event = 0 for "this" event
  19. *  event = -1 for player
  20. *  event = $gameVariables.value(x) to get the event id from variable x
  21. *
  22. *  x, y = coordinates or $gameVariables.value(#) to use a variable coordinate
  23. *
  24. */

  25. (function() {
  26.   var _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
  27.   Game_Interpreter.prototype.pluginCommand = function(command, args) {
  28.     _Game_Interpreter_pluginCommand.call(this, command, args);

  29.     if (command.toUpperCase() === 'SMARTPATH') {
  30.       subject = this.character(eval(args[0]));
  31.       if (args[1].toUpperCase() === 'CANCEL') {
  32.         subject.clearTarget();
  33.       } else if (args.length > 2) {
  34.         subject.setTarget(null, eval(args[1]), eval(args[2]));
  35.       } else {
  36.         subject.setTarget(this.character(eval(args[1])));
  37.       }
  38.     }
  39.   };

  40.   var _Game_CharacterBase_initMembers = Game_CharacterBase.prototype.initMembers;
  41.   Game_CharacterBase.prototype.initMembers = function() {
  42.     _Game_CharacterBase_initMembers.call(this);
  43.     this._target = null;
  44.     this._targetX = null;
  45.     this._targetY = null;
  46.   };

  47.   Game_CharacterBase.prototype.setTarget = function(target, targetX, targetY) {
  48.     this._target = target;
  49.     if (this._target) {
  50.       this._targetX = this._target.x;
  51.       this._targetY = this._target.y;
  52.     } else {
  53.       this._targetX = targetX;
  54.       this._targetY = targetY;
  55.     }
  56.   };

  57.   Game_CharacterBase.prototype.clearTarget = function() {
  58.     this._target = null;
  59.     this._targetX = null;
  60.     this._targetY = null;
  61.   };

  62.   var _Game_CharacterBase_updateStop = Game_CharacterBase.prototype.updateStop;
  63.   Game_CharacterBase.prototype.updateStop = function() {
  64.     _Game_CharacterBase_updateStop.call(this);

  65.     if (this._target) {
  66.       this._targetX = this._target.x;
  67.       this._targetY = this._target.y;
  68.     }

  69.     if (this._targetX != null) {
  70.       direction = this.findDirectionTo(this._targetX, this._targetY);
  71.       if (direction > 0)
  72.       {
  73.         this.moveStraight(direction);
  74.       }
  75.     }
  76.   };
  77. })();
复制代码
回复 支持 1 反对 0

使用道具 举报

Lv5.捕梦者

梦石
0
星屑
30980
在线时间
608 小时
注册时间
2014-7-18
帖子
729

开拓者

2
发表于 2019-10-4 15:09:45 | 只看该作者
我试了一下上面的脚本,使用上面的插件后只会让人物在无法搜到到达NPC所在路径的情况下反复在两个格乱晃,但是试了很多情况都没有报错,建议楼主把出错的地图截个图。
另外,我个人认为珂能是楼主的工程MV版本比较高,导致与脚本不兼容(因为MV版本不断升级导致自带脚本变化了很多,我的测试工程是MV1.2版本的,不排除是因为1.6版本更换了脚本导致出错)
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-11-30 06:54

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表