最近一直在手游 caveboy escape(安卓上,不知道IOS上有没有,可以下来玩玩)。
游戏规则是,在5x5的矩阵,从最下面的起点,每个颜色走三步,到达最上面的重点。
想写个js版本。碰到第一个问题就是,矩阵布局,寻路算法。
网上搜了下只有 PathFinding.js 带有的著名的 A*寻路法(自己百度)
源码:
https://github.com/qiao/PathFinding.js
DEMO:
http://qiao.github.io/PathFinding.js/visual/
但是,做个框架和我的业务不符。PathFinding框架里都是找出最捷径,而我要的是随机路线。
百度了一下,木有雷同或者写的不好,只好自己造轮子。
思前想后,只能用最基本的回溯寻路法,将在一个5x5的矩阵中,随机出不同起点,终点,随机找出不同路线,存储文件,做成不同关卡。
下面附上自己写的‘回溯寻路法’源码:
util.js
define(['node'], function(node) { var Util = { random: function (max){ return Math.floor(Math.random() * ( max + 1)); }, logP: function (point,info){ var t = ' x,y: '+ point.x+' '+point.y; if(info){ t= info + t; } console.log(t) } } return Util; })
node.js
define([], function() { var node = function (x,y){ this.x = x; this.y = y; this.walkable = true; } return node; })
grid.js
define(['node','util'], function(node,util) { var grid = function (option){ this.width = option.width; this.height = option.height; this.grid = []; this._init(); } grid.prototype = { _init: function (){ for(var i=0; i<this.width;i++){ this.grid[i] = []; for(var j=0;j<this.height;j++){ this.grid[i][j] = new node(i,j); } } }, getPointAt: function (x,y){ return this.grid[x][y]; }, isInGrid: function (x,y){ return (x >= 0 && x < this.width) && (y >= 0 && y < this.height); }, isWorkAble: function (x,y){ return this.isInGrid(x,y) && this.getPointAt(x,y).walkable }, getRandomNeighbor: function (point){ var neighbors = this.getNeighbors(point); var r = util.random(neighbors.length - 1); return neighbors[r]; }, getNeighbors: function (point){ var p1,p2,p3,p4; var neighbors = []; if(this.isWorkAble(point.x-1,point.y)){ p1 = this.getPointAt(point.x-1,point.y); neighbors.push(p1); } if(this.isWorkAble(point.x+1,point.y)){ p2 = this.getPointAt(point.x+1,point.y); neighbors.push(p2); } if(this.isWorkAble(point.x,point.y+1)){ p3 = this.getPointAt(point.x,point.y+1); neighbors.push(p3); } if(this.isWorkAble(point.x,point.y-1)){ p4 = this.getPointAt(point.x,point.y-1); neighbors.push(p4); } return neighbors; } } return grid; })
rbpathfinding.js
define(['util'], function(util) { var rbp = function (){ this.grid = null; this.path = []; } rbp.prototype = { getPath: function (ox,oy,dx,dy,grid){ this.grid = grid; var startPoint = grid.getPointAt(ox,oy);//起始点 startPoint.walkable = false; var endPoint = grid.getPointAt(dx,dy);//终点 step = grid.width * grid.height * 2;//最多走这些步数 var next = startPoint; while(step){ step--; next = findNext(next); if(next == 0){ var last = this.path.splice(-1); last[0].walkable = false; next = this.path[this.path.length - 1];//回溯 }else{ next.walkable = false; this.path.push(next); if(next == endPoint){//判断到达 console.log('finish ``````'); var t= ''; for(var i in this.path){ t += '[' + this.path[i].x + ',' + this.path[i].y+'] '; } console.log(t); step = 0;//结束 } } } return this.path; function findNext(point){ var neighbor = grid.getRandomNeighbor(point); if(neighbor){ util.logP(neighbor); return neighbor; }else{ console.log('not found'); return 0; } } }, } return rbp; })
main.js
require.config({ paths: { pathfinding: 'pathfinding', node: 'node', grid: 'grid' } }); require(['node','grid','rbpathfinding','util'], function(node,grid,rbp,util) { var map = { width: 5, height: 5 } var grid = new grid(map) var startNode = { x: util.random(map.width -1 ), y: 0 } var endNode = { x: util.random(map.width - 1), y: map.height - 1 } util.logP(startNode,'Start Point'); util.logP(endNode,'End Point'); //调用 var rbp = new rbp(); var path = rbp.getPath(startNode.x,startNode.y,endNode.x,endNode.y,grid); console.log(path); //Start Point x,y: 4 0 VM10885:11 //End Point x,y: 3 4 //Path [3,0] [2,0] [2,1] [1,1] [1,0] [0,0] [0,1] [0,2] [1,2] [2,2] [2,3] [3,3] [4,3] [4,4] [3,4] })
至此,有了做个回溯算法,游戏可以说做出大半了。