赞 | 1 |
VIP | 0 |
好人卡 | 3 |
积分 | 1 |
经验 | 3075 |
最后登录 | 2016-8-29 |
在线时间 | 53 小时 |
Lv1.梦旅人
- 梦石
- 0
- 星屑
- 50
- 在线时间
- 53 小时
- 注册时间
- 2007-5-3
- 帖子
- 30
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
本帖最后由 r901042004 于 2016-5-9 01:32 编辑
https://rpg.blue/thread-385504-1-1.html
使用這篇的八方向腳本遇到尋路的問題
感謝該篇7樓的 @喵呜喵5 的教學
實作腳本分享給大家
Game_Character.prototype.findDirectionTo = function(goalX, goalY) { var searchLimit = this.searchLimit(); var mapWidth = $gameMap.width(); var nodeList = []; var openList = []; var closedList = []; var start = {}; var best = start; if (this.x === goalX && this.y === goalY) { return 0 } start.parent = null; start.x = this.x; start.y = this.y; start.g = 0; start.f = $gameMap.distance(start.x, start.y, goalX, goalY); nodeList.push(start); openList.push(start.y * mapWidth + start.x); while (nodeList.length > 0) { var bestIndex = 0; for (var i = 0; i < nodeList.length; i++) { if (nodeList[i].f < nodeList[bestIndex].f) { bestIndex = i } } var current = nodeList[bestIndex]; var x1 = current.x; var y1 = current.y; var pos1 = y1 * mapWidth + x1; var g1 = current.g; nodeList.splice(bestIndex, 1); openList.splice(openList.indexOf(pos1), 1); closedList.push(pos1); if (current.x === goalX && current.y === goalY) { best = current; goaled = true; break } if (g1 >= searchLimit) { continue } for (var j = 1; j <= 9; j++) { var direction = j; if (direction == 5) continue var x2 = $gameMap.roundXWithDirection(x1, direction); var y2 = $gameMap.roundYWithDirection(y1, direction); var pos2 = y2 * mapWidth + x2; if (closedList.contains(pos2)) { continue } if (!this.canPass(x1, y1, direction)) { continue } var g2 = g1 + 1; var index2 = openList.indexOf(pos2); if (index2 < 0 || g2 < nodeList[index2].g) { var neighbor; if (index2 >= 0) { neighbor = nodeList[index2] } else { neighbor = {}; nodeList.push(neighbor); openList.push(pos2) } neighbor.parent = current; neighbor.x = x2; neighbor.y = y2; neighbor.g = g2; neighbor.f = g2 + $gameMap.distance(x2, y2, goalX, goalY); if (!best || neighbor.f - neighbor.g < best.f - best.g) { best = neighbor } } } } var node = best; while (node.parent && node.parent !== start) { node = node.parent } var deltaX1 = $gameMap.deltaX(node.x, start.x); var deltaY1 = $gameMap.deltaY(node.y, start.y); if (3 * (-deltaY1) + deltaX1 != 0) return 5 + 3 * (-deltaY1) + deltaX1 return 0 }; Game_Map.prototype.xWithDirection = function(x, d) { var temp = ((d - 4 > 0) ? d - 4 : d - 1); return x + (temp % 3) - 1; }; Game_Map.prototype.yWithDirection = function(y, d) { return y - Math.floor((d - 4) / 3); }; Game_Map.prototype.roundXWithDirection = function(x, d) { return this.roundX(this.xWithDirection(x, d)); }; Game_Map.prototype.roundYWithDirection = function(y, d) { return this.roundY(this.yWithDirection(y, d)); }; Game_Map.prototype.isPassableDiagonally = function(x, y, direction) { var horz = (direction % 3 == 1)? 4 : 6; var vert = (direction < 4)? 2 : 8; var x2 = $gameMap.roundXWithDirection(x, horz); var y2 = $gameMap.roundYWithDirection(y, vert); if (this.isPassable(x, y, vert) && this.isPassable(x, y2, horz)) { return true; } if (this.isPassable(x, y, horz) && this.isPassable(x2, y, vert)) { return true; } return false; }; Game_CharacterBase.prototype.isMapPassable = function(x, y, d) { var x2 = $gameMap.roundXWithDirection(x, d); var y2 = $gameMap.roundYWithDirection(y, d); var d2 = this.reverseDir(d); if (d % 2 == 0) return $gameMap.isPassable(x, y, d) && $gameMap.isPassable(x2, y2, d2); else return $gameMap.isPassableDiagonally(x, y, d) && $gameMap.isPassableDiagonally(x2, y2, d2); };
Game_Character.prototype.findDirectionTo = function(goalX, goalY) {
var searchLimit = this.searchLimit();
var mapWidth = $gameMap.width();
var nodeList = [];
var openList = [];
var closedList = [];
var start = {};
var best = start;
if (this.x === goalX && this.y === goalY) {
return 0
}
start.parent = null;
start.x = this.x;
start.y = this.y;
start.g = 0;
start.f = $gameMap.distance(start.x, start.y, goalX, goalY);
nodeList.push(start);
openList.push(start.y * mapWidth + start.x);
while (nodeList.length > 0) {
var bestIndex = 0;
for (var i = 0; i < nodeList.length; i++) {
if (nodeList[i].f < nodeList[bestIndex].f) {
bestIndex = i
}
}
var current = nodeList[bestIndex];
var x1 = current.x;
var y1 = current.y;
var pos1 = y1 * mapWidth + x1;
var g1 = current.g;
nodeList.splice(bestIndex, 1);
openList.splice(openList.indexOf(pos1), 1);
closedList.push(pos1);
if (current.x === goalX && current.y === goalY) {
best = current;
goaled = true;
break
}
if (g1 >= searchLimit) {
continue
}
for (var j = 1; j <= 9; j++) {
var direction = j;
if (direction == 5)
continue
var x2 = $gameMap.roundXWithDirection(x1, direction);
var y2 = $gameMap.roundYWithDirection(y1, direction);
var pos2 = y2 * mapWidth + x2;
if (closedList.contains(pos2)) {
continue
}
if (!this.canPass(x1, y1, direction)) {
continue
}
var g2 = g1 + 1;
var index2 = openList.indexOf(pos2);
if (index2 < 0 || g2 < nodeList[index2].g) {
var neighbor;
if (index2 >= 0) {
neighbor = nodeList[index2]
} else {
neighbor = {};
nodeList.push(neighbor);
openList.push(pos2)
}
neighbor.parent = current;
neighbor.x = x2;
neighbor.y = y2;
neighbor.g = g2;
neighbor.f = g2 + $gameMap.distance(x2, y2, goalX, goalY);
if (!best || neighbor.f - neighbor.g < best.f - best.g) {
best = neighbor
}
}
}
}
var node = best;
while (node.parent && node.parent !== start) {
node = node.parent
}
var deltaX1 = $gameMap.deltaX(node.x, start.x);
var deltaY1 = $gameMap.deltaY(node.y, start.y);
if (3 * (-deltaY1) + deltaX1 != 0)
return 5 + 3 * (-deltaY1) + deltaX1
return 0
};
Game_Map.prototype.xWithDirection = function(x, d) {
var temp = ((d - 4 > 0) ? d - 4 : d - 1);
return x + (temp % 3) - 1;
};
Game_Map.prototype.yWithDirection = function(y, d) {
return y - Math.floor((d - 4) / 3);
};
Game_Map.prototype.roundXWithDirection = function(x, d) {
return this.roundX(this.xWithDirection(x, d));
};
Game_Map.prototype.roundYWithDirection = function(y, d) {
return this.roundY(this.yWithDirection(y, d));
};
Game_Map.prototype.isPassableDiagonally = function(x, y, direction) {
var horz = (direction % 3 == 1)? 4 : 6;
var vert = (direction < 4)? 2 : 8;
var x2 = $gameMap.roundXWithDirection(x, horz);
var y2 = $gameMap.roundYWithDirection(y, vert);
if (this.isPassable(x, y, vert) && this.isPassable(x, y2, horz)) {
return true;
}
if (this.isPassable(x, y, horz) && this.isPassable(x2, y, vert)) {
return true;
}
return false;
};
Game_CharacterBase.prototype.isMapPassable = function(x, y, d) {
var x2 = $gameMap.roundXWithDirection(x, d);
var y2 = $gameMap.roundYWithDirection(y, d);
var d2 = this.reverseDir(d);
if (d % 2 == 0)
return $gameMap.isPassable(x, y, d) && $gameMap.isPassable(x2, y2, d2);
else
return $gameMap.isPassableDiagonally(x, y, d) && $gameMap.isPassableDiagonally(x2, y2, d2);
};
腳本有點亂請包涵
更改的地方:
WithDirection、RoundWidthDirection需要八方向的判定
以及isMapPassable也需要八方向的判定
若要更改搜尋的距離請用
Game_Character.prototype.searchLimit = function() { return 12; };
Game_Character.prototype.searchLimit = function() {
return 12;
};
將12改得更大即可
數值太大且玩家點在不可到達之位置
會造成嚴重的卡頓(實測200很卡)
尤其是玩家點在事件上
解決辦法我猜是先判定點的是否為不可移動之位置
然後再往外找到一個可移動之位置(有點從迷宮出口倒推路徑的感覺..)
還有利用地圖R層判定這個地方到底能不能走
綜合起來應該就是很厲害的尋路腳本了 |
评分
-
查看全部评分
|