KUOKUO 흥미로운 기사의 CocosCreator : 스타의 길 찾기는 자세한 몹

면책 조항 :이 문서는 블로거 원본입니다, 추적 에 의해-SA의 CC 4.0 저작권 계약, 복제, 원본 소스 링크이 문을 첨부 해주세요.
이 링크 : https://blog.csdn.net/kuokuo666/article/details/94590258

당신이 이해할 수 있도록 분석을 자세히 폭도에 대한 일련의 기사에.
텍스트
첫째, 맨하탄 평가 방법.
추가 및 기간의 직선 거리 또는 행에서 몇 단락으로 이해 할 수 있습니다.
여기에 그림 삽입 설명

// 曼哈顿估价法,传入当前点与目标点,返回估值
// 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)는 물론, 그래서 당신이 붙어 일으키는 것을 방지하기 위해 경로를 찾을 수 없습니다으로 .. 각 사이클을 이해된다.
그리고 우리가 출발점으로 객체를 생성 할 수 있습니다. 그리고 가까운리스트에 배치.
이러한 점 가득 확대리스트 닫기, 검색의 완료에 열기의 하부 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 성장 호르몬 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);
},

루프 개폐 여부 개의 목록을 결정

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