查看: 4671|回复: 1

[原创发布] 八方向自動尋路

[复制链接]
梦石
0
星屑
50
在线时间
53 小时
注册时间
2007-5-3
回帖
25
发表于 2016-5-9 01:29:38 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 r901042004 于 2016-5-9 01:32 编辑

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

[pre lang="javascript" line="1"]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.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);      
};[/pre]


腳本有點亂請包涵

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

若要更改搜尋的距離請用

[pre lang="javascript" line="1"]Game_Character.prototype.searchLimit = function() {
    return 12;
};[/pre]

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

解決辦法我猜是先判定點的是否為不可移動之位置
然後再往外找到一個可移動之位置(有點從迷宮出口倒推路徑的感覺..)
還有利用地圖R層判定這個地方到底能不能走
綜合起來應該就是很厲害的尋路腳本了

评分

参与人数 1赞 +1 收起 理由
yqfans + 1

查看全部评分

梦石
0
星屑
94
在线时间
20 小时
注册时间
2009-4-15
回帖
40
发表于 2018-1-20 00:36:38 | 显示全部楼层
非常好的,实现了鼠标8方向寻路,配合八方向行走插件,完美实现效果!赞!
回复

使用道具 举报

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

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部