简单的自动规避障碍物(寻路)写法


这是成品,可以看到黑色的方块会自动躲避红色的方块

这是项目结构,每个方块的尺寸都为25*25
新建三个脚本文件role.ts Map.ts obstacle.ts

//Map.ts
const { ccclass, property } = cc._decorator;
export interface Pos {
    x: number,
    y: number,

    f?: number
}
@ccclass
export default class NewClass extends cc.Component {


    //障碍物位置信息
    obstaclePos: Pos[] = []

    //role节点
    role: cc.Node = null

    onLoad() {
        this.role = this.node.getChildByName('role')
        this.node.on(cc.Node.EventType.MOUSE_DOWN, this.updateDestination, this)

    }


    //鼠标按下更新目的地位置
    updateDestination(event: cc.Event.EventTouch) {
        
        
        let pos: cc.Vec2 = event.getLocation();
        pos = this.node.convertToNodeSpaceAR(pos);
        let isOb = false;
        
        
        if (this.obstaclePos.length != 0) {
            for (let i = 0; i < this.obstaclePos.length; i++) {
                if (this.obstaclePos[i].x != Math.round(pos.x / 25) * 25 || this.obstaclePos[i].y != Math.round(pos.y / 25) * 25) {
                    continue;
                }
                isOb = true;
            }
        }

        

        if (!isOb) {
            let roleJs = this.role.getComponent('role');
            //初始化
            roleJs.destination = { x: Math.round(pos.x / 25) * 25, y: Math.round(pos.y / 25) * 25 };
            roleJs.alreayRoad = []

            roleJs.begin = { x: this.role.x, y: this.role.y }
            roleJs.alreayRoad.push({ x: this.role.x, y: this.role.y })

        }
    }
}

接着是障碍物脚本

const { ccclass, property } = cc._decorator;

import Map, { Pos } from './Map';

@ccclass

export default class NewClass extends cc.Component {

    //地图脚本

    mapTs: Map = null

    //地图节点

    mapNode: cc.Node = null

    onLoad() {

        this.mapTs = this.node.parent.getComponent('Map');

        this.mapNode = this.node.parent

        this.setObstaclePos()

    }

    //障碍物位置信息,存进地图脚本里

    setObstaclePos() {

        let targetPos: Pos[] = this.mapTs.obstaclePos;

        targetPos.push({ x: this.node.x, y: this.node.y });

    }

    start() {

    }

    update(dt) {

    }

}

然后挂载到角色身上的脚本


import { Pos } from "./Map";

const { ccclass, property } = cc._decorator;


@ccclass
export default class NewClass extends cc.Component {

    //目的地位置
    destination: Pos = null


    //起点方格
    begin: Pos = null
    
    //已经走过的路径
    alreayRoad: Pos[] = [];
    //计数一秒
    onLoad() {



    }

    start() {

    }


    update(dt) {

        if (this.destination && this.begin && (this.destination.x != this.begin.x || this.destination.y != this.begin.y)) {
           
            this.filterObstacle(this.begin)
            this.node.x = this.begin.x;
            this.node.y = this.begin.y;
        }

        if (this.destination&&this.begin&&this.destination.x == this.begin.x && this.destination.y == this.begin.y) {
            this.alreayRoad = []
            this.begin = null
        }
    }

    //过滤路径周围障碍物方格
    filterObstacle(pos: Pos) {


        //起点周围的八个格子
        let list: Pos[] = [{ x: pos.x + 25, y: pos.y, f: 10 + (Math.abs(pos.x + 25 - this.destination.x) / 25 + Math.abs(pos.y - this.destination.y) / 25) * 10 },
        { x: pos.x - 25, y: pos.y, f: 10 + (Math.abs(pos.x - 25 - this.destination.x) / 25 + Math.abs(pos.y - this.destination.y) / 25) * 10 },
        { x: pos.x, y: pos.y + 25, f: 10 + (Math.abs(pos.x - this.destination.x) / 25 + Math.abs(pos.y + 25 - this.destination.y) / 25) * 10 },
        { x: pos.x, y: pos.y - 25, f: 10 + (Math.abs(pos.x - this.destination.x) / 25 + Math.abs(pos.y - 25 - this.destination.y) / 25) * 10 },
        { x: pos.x + 25, y: pos.y + 25, f: 14 + (Math.abs(pos.x + 25 - this.destination.x) / 25 + Math.abs(pos.y + 25 - this.destination.y) / 25) * 10 },
        { x: pos.x + 25, y: pos.y - 25, f: 14 + (Math.abs(pos.x + 25 - this.destination.x) / 25 + Math.abs(pos.y - 25 - this.destination.y) / 25) * 10 },
        { x: pos.x - 25, y: pos.y - 25, f: 14 + (Math.abs(pos.x - 25 - this.destination.x) / 25 + Math.abs(pos.y - 25 - this.destination.y) / 25) * 10 },
        { x: pos.x - 25, y: pos.y + 25, f: 14 + (Math.abs(pos.x - 25 - this.destination.x) / 25 + Math.abs(pos.y + 25 - this.destination.y) / 25) * 10 }];
        //获取障碍物位置数组
        let obstaclePosList = this.node.parent.getComponent('Map').obstaclePos


        //过滤完障碍物的数组
        let filterObList: Pos[] = []
        //过滤障碍物
            
        for (let i = 0; i < list.length; i++) {
            let isOb =false
            for (let j = 0; j < obstaclePosList.length; j++) {
                if (list[i].x != obstaclePosList[j].x||list[i].y != obstaclePosList[j].y) {
                    continue;
                }
                isOb = true;
                break;
            }
            if (!isOb) {
                filterObList.push(list[i])
            }
        }
        
        //过滤已经走过的路径
        let lastList:Pos[] = []
        for (let i = 0; i < filterObList.length; i++) {
            let isOb = false
            for (let j = 0; j < this.alreayRoad.length; j++) {
                if (filterObList[i].x != this.alreayRoad[j].x || filterObList[i].y != this.alreayRoad[j].y) {
                    continue;
                }
                isOb = true;
                break;
            }
            if (!isOb) {
                lastList.push(filterObList[i])
            }
        }


        let min = lastList[0].f
        let minIndex = 0
        for (let i = 0; i < lastList.length; i++) {
            if (lastList[i].f <= min) {
                min = lastList[i].f
                minIndex = i
            }
        }
        this.alreayRoad.push(lastList[minIndex])
      
        this.begin = lastList[minIndex]
        
       
    }

}

1赞

:+1: :+1: :+1: :+1: :+1: