CocosCreator of KUOKUO interesting article: A star pathfinding mobs Detailed

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/kuokuo666/article/details/94590258

On a series of articles on mobs detailed analysis to help you understand.
Text
First, Manhattan valuation method.
You can add and understood as a straight-line distance of a period or a few paragraphs from the line.
Here Insert Picture Description

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

Then let us analyze the target point on the path should have the information.
Here Insert Picture Description

// 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;

By-step demonstration

Data start in a statement.

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

Limit 500 is well understood, each cycle time-- so you can not find the path to prevent causing stuck.
Then let us create an object as a starting point. And then placed in close list.
close list filled with those points have been searched, open the list into points to be selected, and then choose a lower f-point list in the open, into the close, the completion of a search. Until we find the finish line.

	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);
    	},

Shown
Here Insert Picture Description
us from the start, looking around the current point of a circle, and then calculates the value of f gh get.

while (true) {
    time--;
    // 周围一圈装入 open
    this.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;
    }
}

Looking to the surrounding

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;
        }
        // 装入 open
        this.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];
},

The method is placed close list directly into close array, we need to create a list of open information point, because it is a new point.

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);
},

In determining whether two open close list for loop

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;
},

Finally, we find that
in a lot of close points list is found, the array must be the final destination point.
Here Insert Picture Description
In the final target point is close array, we just according to the target point, for continuous upward access parent can go back to the starting point.
Here Insert Picture Description
Code

// 根据 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);

Walk along the path is very simple, use runAction continue to go until the finish

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)
    ));
},

Row and column coordinates and the actual coordinates into

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

Well, I do not know little friends do not understand this time!
O (∩_∩) O ~~

Guess you like

Origin blog.csdn.net/kuokuo666/article/details/94590258