摘要
在寻路算法中我们一般使用网格来进行搜索判断,在没接触时自己也好奇怎么生成地图下的网格,我相信也有很多朋友存在好奇,这里简单分享下个人的解决方案,有错误还希望大佬们多多指导。DOME地址
版本说明
使用 CocosCreator 的 2.4.3 版本。
开始
效果演示:
红色代表一个正方形的中心点
蓝色表示该正方形区域为障碍物

逻辑梳理:
- 设置地图节点大小,设置锚点位于左下角(0,0)位置
- 获取单个正方形的边长大小
- 获取节点下的障碍物并得到具体的行数、列数方便生成布局时标记为改点为障碍物
- 生成布局
一、设置地图等:
1.我们在Canvas下新建一个map节点,需要给map节点设置对应的宽度高度,该节点的大小就代表地图的大小,这里我使用的是960 640的画布。
2.并且需要把map节点的Anchor锚点设置到左下角(0,0),使map节点位于第一象限中,这样做的原因是方便计算正方形的大小、位置。

3.正方形预制体节点

二、获取正方形的边长大小:
1.获取当前地图map节点的大小,计算需要生成正方形的大小、需要生成多少。
计算逻辑为,初始设定一个正方形的大小,循环通过高度 宽度 / 正方形大小 得到一个可以被整除的最终正方形大小。
列:画布宽度为 960 高度为 640 初始定义正方形大小为 30
960 / 30 = 32 640 / 30 = 21.33333333333333 不满足整除条件 使默认正方形大小 +1
960 / 31 = 30.96774193548387 640 / 31 = 20.64516129032258 不满足整除条件 使默认正方形大小 +1
960 / 32 = 30 640 / 32 = 20 条件满足故正方形大小为 32
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
calculateSquareHeight (){ let _mapHeight = this.node.height; let _mapWidth = this.node.width; let _alt = 30; let _isEnd = true; while (_isEnd) { let _longNum = _mapHeight / _alt; let _widthNum = _mapWidth / _alt; if(_longNum % 1 === 0 && _widthNum % 1 ===0){ _isEnd = false; this.altSize = _alt; this.longNum = _longNum; this.widthNum = _widthNum; this.mapForObstacle(); } else { _alt++; } } }
|
三、获取节点下的障碍物:
1.如果地图中存在障碍物,我们需要通过设置group把障碍物的分组设置为’MAP_OBSTACLE’,然后进行循环获取每个节点计算当前节点所在的行数、列数并存入Map方便生成布局时判断。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
mapForObstacle (){ let a = 'Canvas/map/level' let mapNode = cc.find(a); mapNode.children.forEach((r)=>{ if(r.group === 'MAP_OBSTACLE'){ let _widthRadius = r.width - r.width / 2; let _heightRadius = r.height - r.height / 2; let _xRange = r.x - _widthRadius; let _yRange = r.y - _heightRadius; let _columnLeft = Math.ceil(_xRange / this.altSize); let _columnRight = Math.ceil((r.x + _widthRadius) / this.altSize); let _a = []; for(let i = 0,len = _columnRight -_columnLeft;i<=len;i++){ _a[i] = _columnLeft + i; }; let _lineDow = Math.ceil(_yRange / this.altSize); let _lineUp = Math.ceil((r.y + _heightRadius) / this.altSize); let _b = []; for(let i = 0,len = _lineUp -_lineDow;i<=len;i++){ _b[i] = _lineDow + i; }; _b.forEach((r)=>{ let _obsGet = this.obstacleMap.get(r); if(_obsGet){ let _arr1 = [..._a,..._obsGet]; let _arr = Array.from(new Set(_arr1)); this.obstacleMap.set(r,_arr);
} else { this.obstacleMap.set(r,_a); } }); } }) this.generateLayout(this.altSize,this.longNum,this.widthNum); }
|
四、生成布局:
1.根据已经得到的数据进行网格的生成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
|
generateLayout (_initSquareHeight:number,_initLineNum:number,_initColumnNum:number){ let _lineNum = 1; let _columnNum = 1; let _radii = _initSquareHeight / 2; let _isEnd = true; let _arr = []; while (_isEnd) { let _x = _columnNum === 1 ? _columnNum *_radii : (_columnNum-1) * _initSquareHeight + _radii; let _y = _lineNum === 1 ? _lineNum *_radii : (_lineNum-1) * _initSquareHeight + _radii; let _isObsLine = this.obstacleMap.get(_lineNum); let _color = new cc.Color(255,0,0); let _type = 0; if(_isObsLine && _isObsLine.indexOf(_columnNum) >= 0){ _color = new cc.Color(71,53,234); _type = 1; } let _node = cc.instantiate(this.ItemPrefab); _node.width = _initSquareHeight; _node.height = _initSquareHeight; _node.children[0].color = _color; _node.setPosition(cc.v2(_x,_y)); _node.parent = this.ItemNode; _arr.push({type:_type,node:_node}); if(_lineNum === _initLineNum && _columnNum === _initColumnNum){ _isEnd = false; _arr = []; } else if(_columnNum === _initColumnNum){ _columnNum = 1; _lineNum++; _arr = []; } else { _columnNum++; } } }
|
结尾:
暂时行更新,写这写这写不下去了…