KUOKUO興味深い記事のCocosCreator:詳細モブを経路探索星

免責事項:この記事はブロガーオリジナル記事です、続くBY-SAのCC 4.0を著作権契約、複製、元のソースのリンクと、この文を添付してください。
このリンク: https://blog.csdn.net/kuokuo666/article/details/94590258

あなたが理解するためのmob詳細な分析上の一連の記事で。
テキスト
まず、マンハッタンの評価方法。
あなたは、追加してラインからの期間または数段落の直線距離として理解することができます。
ここに画像を挿入説明

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

そして、私たちは情報を持っている必要があり、パス上の目標点を分析してみましょう。
ここに画像を挿入説明

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

ステップバイステップのデモ

データは声明の中でスタート。

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

制限500は十分なので、あなたが立ち往生原因防ぐためにパスを見つけることができませんtime--各サイクルを理解されています。
そして、私たちは出発点としてオブジェクトを作成してみましょう。[閉じるリストに入れました。
これらの点で満たされた近隣リストは、近くに、オープンに低いF点リストを選択し、検索の完了を選択する点にリストを開き、検索、およびされています。私たちは、フィニッシュラインを見つけるまで。

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

示さ
ここに画像を挿入説明
円の現在のポイントを中心に見て、最初から私たちを、その後の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;
    }
}

周囲に目を向けます

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

この方法は、近い配列に直接密接リストを置いていることが新しい点であるので、我々は、オープンな情報ポイントのリストを作成する必要があります。

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

2は、ループの近くにリストを開くかどうかを判断するには

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

最後に、我々はそれを見つける
近い点リストの多くで発見され、配列は、最終目的地のポイントでなければなりません。
ここに画像を挿入説明
最終目標地点に近い配列は、我々だけで目標点に応じて、継続的な上向きのアクセス親のための出発点に戻ることができています。
ここに画像を挿入説明
コードの実装

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

runAction関数がフィニッシュまで行くために引き続き使用し、非常に単純であるパスに沿って歩きます

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

行および列の座標と実際の座標に

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

まあ、私は少しの友人がこの時間を理解していないかわかりません!
O(∩_∩)O ~~

おすすめ

転載: blog.csdn.net/kuokuo666/article/details/94590258