A*算法在Canvas中的渲染实现(JS版本)

体验链接(需要复制到浏览器):http://118.89.184.186/as/ 

index.html



    
        
        A*寻路算法
    
    
        
    
    

main.js

/**获取画布 */
const canvas = document.querySelector('canvas');
/**获取2d画笔 */
const ctx = canvas.getContext('2d');
/**格子空间分别率大小 */
const space = 20;
/**格子行数 */
var row = undefined;
/**格子列数 */
var column = undefined;
/**矩阵布局(0:可走,2:障碍物) */
var matrix = undefined;
/**始点 */
var startNode = undefined;
/**终点 */
var endNode = undefined;
/**开放节点列表 */
var openList = undefined;
/**关闭节点列表 */
var closeList = undefined;
/**点击允许 */
var canClick = true;
/**
 * 节点构造函数
 * @param {number} x x轴坐标
 * @param {number} y y轴坐标
 * @param {Node} parent 父节点
 * @returns {Node} 新节点
 */
function Node(x,y,parent){
    this.x = x;
    this.y = y;
    this.parent = parent;
    //g值表示始点到当前节点的移动代价
    if(this.parent){
        this.g = this.parent.g + 1;
    }else{
        this.g = 0;
    }
    //h值表示当前节点到终点的曼哈顿距离(忽略障碍物)
    if(this.endNode){
        this.h = Math.abs(endNode.x-this.x) + Math.abs(endNode.y-this.y);
    }else{
        this.h = 0;
    }
    //f值表示g值和h值之和
    this.f = this.g + this.h;
}
/**
 * 坐标相等判断函数
 * @param {Node} node 对比节点
 * @returns {boolean} 坐标是否相等
 */
Node.prototype.equal = function(node){
    if(node.x==this.x&&node.y==this.y){
        return true;
    }else{
        return false;
    }
}
/**
 * 代价评估值比较
 * @param {Node} node 对比节点
 * @returns {number} 代价评估差值
 */
Node.prototype.compareTo = function(node){
    return this.f-node.f;
}
/**关闭节点 */
Node.prototype.close = function(){
    let list = new Array();
    let index = openList.indexOf(this);
    for(let i=0;icolumn-1)return;
    if(y<0||y>row-1)return;
    if(matrix[y][x]==2)return;
    let newNode = new Node(x,y,node);
    let openNode = newNode.getFromOpenList();
    let closeNode = newNode.getFromCloseList();
    if(!openNode&&!closeNode){
        openList.push(newNode);
    }else if(openNode&&newNode.compareTo(openNode)<0){
        openNode.update(newNode);
    }
}
/**
 * 获取最优节点
 * @returns {Node} 最优节点
 */
Node.getBestNode = function(){
    openList.sort((a,b)=>{
        return a.compareTo(b);
    });
    if(openList.length>0){
        return openList[0];
    }else{
        return null;
    }
}
/**设置窗口大小变化监听事件 */
window.onresize = function(){
    //行列数初始化
    row = Math.floor(window.innerHeight/space)>1?Math.floor(window.innerHeight/space)-1:1;
    column = Math.floor(window.innerWidth/space)>1?Math.floor(window.innerWidth/space)-1:1;
    //清洗画布
    ctx.clearRect(0,0,canvas.width,canvas.height);
    //画布大小初始化
    canvas.width = column*space;
    canvas.height = row*space;
    //设置线段宽度
    ctx.lineWidth = 1;
    //设置线段颜色(黑色)
    ctx.strokeStyle = 'rgb(0,0,0)';
    //绘制网格竖线
    for(let i=0;i0){
        setTimeout(() => {
            let node = outList.pop();
            recycleList.push(node);
            ctx.fillRect(node.x*space+1,node.y*space+1,space-2,space-2);
            outputPath(outList,recycleList,outputInterval,recycleInterval);
        }, outputInterval);
    }else{
        //回收路径
        recyclePath(recycleList,recycleInterval);
    }
}
/**
 * 回收路径
 * @param {Node[]} recycleList //路径节点回收列表
 * @param {number} recycleInterval //路径节点回收时间间隔
 */
function recyclePath(recycleList,recycleInterval){
    if(recycleList.length>1){
        setTimeout(() => {
            let node = recycleList.shift();
            ctx.clearRect(node.x*space+1,node.y*space+1,space-2,space-2);
            recyclePath(recycleList,recycleInterval);
        }, recycleInterval);
    }else{
        canClick = true;
    }
}

 

你可能感兴趣的:(JS,A*算法)