当前位置: 首页 > Web前端 > HTML5

Canvas实例---制作一个简单的迷宫

时间:2023-04-06 00:19:13 HTML5

本系列分为两部分,第一部分是迷宫的生成和运行,第二部分是自动寻路算法。先看效果:点击查看开门见山,先说说生成迷宫的思路。整个思路很简单:首先,我们把迷宫看成m行n列的单元格组合,每个单元格可以表示为maze[i][j]。迷宫和m*n单元有什么区别?是的,迷宫相当于不同的格子按照一定的规则相互连接,也就是说我们去掉相邻两个格子之间的重合线,然后按照一定的规则循环生成迷宫。我们假设我们从左上角开始,遍历每个单元格。如果单元格没有被访问过,检查其相邻元素(上、下、左、右)是否有未访问过的单元格,如果有,则随机取出一个相邻元素,并打开它们之间的重合线,如果没有,则返回前一个单元格。上面的代码:首先我们创建一个构造函数:functionMaze(obj,col,row){this.col=col||10;this.row=行||10;this.canvas=obj.getContext('2d');this.init();}在这个构造函数中,我们接收三个参数,分别是canvas元素,迷宫的行数和列数,直接调用Maze的init方法。init:function(){this.cell=(width-2)/this.col;for(vari=0;i=0&&!maze_cells[x-1][y].isVisited){neighbors.push({'x':x-1,'y':y})}if(x+1=0&&!maze_cells[x][y-1].isVisited){neighbors.push({'x':x,'y':y-1})}if(y+10){//相邻房间有未访房间varcurrent={'x':x,'y':y};varnext=neighbors[Math.floor(Math.random()*neighbors.length)];maze_cells[next.x][next.y].isVisited=true;visitRooms.push({'x':next.x,'y':next.y})roomsLine.push({'x':next.x,'y':next.y});this.breakWall(当前,下一个);this.calcCells(next.x,next.y,arr)}else{varnext=roomsLine.pop();如果(下一个!=null){this.calcCells(next.x,next.y,arr)}}},我们看到如果当前单元格还有未访问的相邻单元格,就会执行breakWall方法,即当前单元格会打开相邻单元格之间的墙,当然我们应该随机选择一个未访问过的相邻单元格我们通过设置单元格的top、bottom、left、right属性为true或false来判断这个方向是否应该有边框,同时,方向是否可以走。breakWall:function(cur,next){if(cur.xnext.x){maze_cells[cur.x][cur.y].top=true;maze_cells[next.x][next.y].bottom=true;}if(cur.ynext.y){maze_cells[cur.x][cur.y].left=true;maze_cells[next.x][next.y].right=true;}},经过上面两步,我们完整的数组就已经成型了,接下来就可以开始绘制了。top、left、right、bottom为false时有边框,为true时无边框。这一步比较简单。我们在最后调用了一个drawOffset方法,它会创建一个离屏对象,这样我们在动态修改迷宫的时候就可以直接将离屏图像绘制到当前画布上。drawCells:function(){varctx=this.canvas,//画布对象w=this.cell;ctx.clearRect(0,0,$('canvas').width,$('canvas').height)ctx.beginPath();ctx.save();ctx.translate(1,1)ctx.strokeStyle='#000000';ctx.lineWidth=2;for(variinmaze_cells){//i为行varlen=maze_cells[i].length;for(varj=0;j