Project1

标题: 八方向自動尋路 [打印本页]

作者: r901042004    时间: 2016-5-9 01:29
标题: 八方向自動尋路
本帖最后由 r901042004 于 2016-5-9 01:32 编辑

https://rpg.blue/thread-385504-1-1.html
使用這篇的八方向腳本遇到尋路的問題
感謝該篇7樓的 @喵呜喵5 的教學
實作腳本分享給大家

JAVASCRIPT 代码复制
  1. Game_Character.prototype.findDirectionTo = function(goalX, goalY) {
  2.     var searchLimit = this.searchLimit();
  3.     var mapWidth = $gameMap.width();
  4.     var nodeList = [];
  5.     var openList = [];
  6.     var closedList = [];
  7.     var start = {};
  8.     var best = start;
  9.     if (this.x === goalX && this.y === goalY) {
  10.         return 0
  11.     }
  12.     start.parent = null;
  13.     start.x = this.x;
  14.     start.y = this.y;
  15.     start.g = 0;
  16.     start.f = $gameMap.distance(start.x, start.y, goalX, goalY);
  17.     nodeList.push(start);
  18.     openList.push(start.y * mapWidth + start.x);
  19.     while (nodeList.length > 0) {
  20.         var bestIndex = 0;
  21.         for (var i = 0; i < nodeList.length; i++) {
  22.             if (nodeList[i].f < nodeList[bestIndex].f) {
  23.                 bestIndex = i
  24.             }
  25.         }
  26.         var current = nodeList[bestIndex];
  27.         var x1 = current.x;
  28.         var y1 = current.y;
  29.         var pos1 = y1 * mapWidth + x1;
  30.         var g1 = current.g;
  31.         nodeList.splice(bestIndex, 1);
  32.         openList.splice(openList.indexOf(pos1), 1);
  33.         closedList.push(pos1);
  34.         if (current.x === goalX && current.y === goalY) {
  35.             best = current;
  36.             goaled = true;
  37.             break
  38.         }
  39.         if (g1 >= searchLimit) {
  40.             continue
  41.         }
  42.         for (var j = 1; j <= 9; j++) {
  43.             var direction = j;
  44.             if (direction == 5)
  45.                 continue   
  46.             var x2 = $gameMap.roundXWithDirection(x1, direction);
  47.             var y2 = $gameMap.roundYWithDirection(y1, direction);
  48.             var pos2 = y2 * mapWidth + x2;
  49.             if (closedList.contains(pos2)) {
  50.                 continue
  51.             }
  52.             if (!this.canPass(x1, y1, direction)) {
  53.                 continue
  54.             }
  55.             var g2 = g1 + 1;
  56.             var index2 = openList.indexOf(pos2);
  57.             if (index2 < 0 || g2 < nodeList[index2].g) {
  58.                 var neighbor;
  59.                 if (index2 >= 0) {
  60.                     neighbor = nodeList[index2]
  61.                 } else {
  62.                     neighbor = {};
  63.                     nodeList.push(neighbor);
  64.                     openList.push(pos2)
  65.                 }
  66.                 neighbor.parent = current;
  67.                 neighbor.x = x2;
  68.                 neighbor.y = y2;
  69.                 neighbor.g = g2;
  70.                 neighbor.f = g2 + $gameMap.distance(x2, y2, goalX, goalY);
  71.                 if (!best || neighbor.f - neighbor.g < best.f - best.g) {
  72.                     best = neighbor
  73.                 }
  74.             }
  75.         }
  76.     }
  77.     var node = best;
  78.     while (node.parent && node.parent !== start) {
  79.         node = node.parent
  80.     }
  81.     var deltaX1 = $gameMap.deltaX(node.x, start.x);
  82.     var deltaY1 = $gameMap.deltaY(node.y, start.y);        
  83.     if (3 * (-deltaY1) + deltaX1 != 0)
  84.         return 5 + 3 * (-deltaY1) + deltaX1
  85.     return 0
  86. };
  87.  
  88. Game_Map.prototype.xWithDirection = function(x, d) {
  89.     var temp = ((d - 4 > 0) ? d - 4 : d - 1);
  90.     return x + (temp % 3) - 1;
  91. };
  92.  
  93. Game_Map.prototype.yWithDirection = function(y, d) {
  94.     return y - Math.floor((d - 4) / 3);
  95. };
  96.  
  97. Game_Map.prototype.roundXWithDirection = function(x, d) {
  98.     return this.roundX(this.xWithDirection(x, d));
  99. };
  100.  
  101. Game_Map.prototype.roundYWithDirection = function(y, d) {
  102.     return this.roundY(this.yWithDirection(y, d));
  103. };
  104.  
  105. Game_Map.prototype.isPassableDiagonally = function(x, y, direction) {
  106.     var horz = (direction % 3 == 1)? 4 : 6;
  107.     var vert = (direction < 4)? 2 : 8;
  108.     var x2 = $gameMap.roundXWithDirection(x, horz);
  109.     var y2 = $gameMap.roundYWithDirection(y, vert);
  110.     if (this.isPassable(x, y, vert) && this.isPassable(x, y2, horz)) {
  111.         return true;
  112.     }
  113.     if (this.isPassable(x, y, horz) && this.isPassable(x2, y, vert)) {
  114.         return true;
  115.     }
  116.     return false;
  117. };
  118.  
  119. Game_CharacterBase.prototype.isMapPassable = function(x, y, d) {
  120.     var x2 = $gameMap.roundXWithDirection(x, d);
  121.     var y2 = $gameMap.roundYWithDirection(y, d);
  122.     var d2 = this.reverseDir(d);
  123.     if (d % 2 == 0)
  124.         return $gameMap.isPassable(x, y, d) && $gameMap.isPassable(x2, y2, d2);
  125.     else
  126.         return $gameMap.isPassableDiagonally(x, y, d) && $gameMap.isPassableDiagonally(x2, y2, d2);      
  127. };



腳本有點亂請包涵

更改的地方:
WithDirection、RoundWidthDirection需要八方向的判定
以及isMapPassable也需要八方向的判定

若要更改搜尋的距離請用

JAVASCRIPT 代码复制
  1. Game_Character.prototype.searchLimit = function() {
  2.     return 12;
  3. };


將12改得更大即可
數值太大且玩家點在不可到達之位置
會造成嚴重的卡頓(實測200很卡)
尤其是玩家點在事件上

解決辦法我猜是先判定點的是否為不可移動之位置
然後再往外找到一個可移動之位置(有點從迷宮出口倒推路徑的感覺..)
還有利用地圖R層判定這個地方到底能不能走
綜合起來應該就是很厲害的尋路腳本了
作者: yqfans    时间: 2018-1-20 00:36
非常好的,实现了鼠标8方向寻路,配合八方向行走插件,完美实现效果!赞!




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1