GameModel.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. import CellModel from "./CellModel";
  2. import {mergePointArray,exclusivePoint} from "../Utils/ModelUtils";
  3. import {ANITIME, CELL_BASENUM, CELL_STATUS, CELL_TYPE, GRID_HEIGHT, GRID_WIDTH} from "./ConstValue";
  4. export default class GameModel {
  5. constructor() {
  6. this.cells = null;
  7. this.cellBgs = null;
  8. this.lastPos = cc.v2(-1,-1);
  9. this.cellTypeNum = 5;
  10. this.cellCreateType = []; //生成种类只在这个数组里面查找
  11. this.crushNums = 0; //消除的块数
  12. // this.curGridPos = {};
  13. }
  14. init(cellTypeNum){
  15. this.cells = [];
  16. this.setCellTypeNum(cellTypeNum || this.cellTypeNum);
  17. for (let i = 1; i <= GRID_WIDTH; i++){
  18. this.cells[i] = [];
  19. for (let j = 1; j <= GRID_HEIGHT; j++){
  20. this.cells[i][j] = new CellModel()
  21. }
  22. }
  23. //this.mock()
  24. for (let i = 1; i <= GRID_WIDTH; i++){
  25. for (let j = 1; j <= GRID_HEIGHT; j++){
  26. //已经被mock数据生成了
  27. if (this.cells[i][j].type != null){
  28. continue;
  29. }
  30. let flag = true;
  31. while (flag){
  32. flag = false;
  33. this.cells[i][j].init(this.getRandomCellType());
  34. let result = this.checkPoint(j, i)[0];
  35. if (result.length > 2){
  36. flag = true;
  37. }
  38. this.cells[i][j].setXY(j, i);
  39. this.cells[i][j].setStartXY(j, i);
  40. }
  41. }
  42. }
  43. }
  44. mock(){
  45. // this.mockInit(5,1,CELL_TYPE.A);
  46. // this.mockInit(5,3,CELL_TYPE.A);
  47. // this.mockInit(4,2,CELL_TYPE.A);
  48. // this.mockInit(3,2,CELL_TYPE.A);
  49. // this.mockInit(5,2,CELL_TYPE.B);
  50. // this.mockInit(6,2,CELL_TYPE.B);
  51. // this.mockInit(7,3,CELL_TYPE.B);
  52. // this.mockInit(8,2,CELL_TYPE.A);
  53. this.mockInit(1, 1, CELL_TYPE.A);
  54. this.mockInit(1, 2, CELL_TYPE.A);
  55. this.mockInit(1, 3, CELL_TYPE.A);
  56. this.mockInit(1, 5, CELL_TYPE.A);
  57. this.mockInit(2, 1, CELL_TYPE.B);
  58. this.mockInit(2, 2, CELL_TYPE.B);
  59. this.mockInit(2, 3, CELL_TYPE.B);
  60. this.mockInit(2, 5, CELL_TYPE.B);
  61. this.mockInit(3, 4, CELL_TYPE.A);
  62. this.mockInit(4, 4, CELL_TYPE.A);
  63. console.log("mock")
  64. }
  65. mockInit(x, y, type){
  66. this.cells[x][y].init(type);
  67. this.cells[x][y].setXY(y, x);
  68. this.cells[x][y].setStartXY(y, x);
  69. }
  70. /**
  71. *
  72. * @param x
  73. * @param y
  74. * @param recursive 是否递归查找
  75. * @returns {([]|string|*)[]}
  76. */
  77. checkPoint(x, y, recursive){
  78. // console.log("递归了x",x)
  79. // console.log("递归了y",y)
  80. let rowResult = this.checkWithDirection(x, y, [cc.v2(1,0),cc.v2(-1,0)]);
  81. let colResult = this.checkWithDirection(x, y, [cc.v2(0,-1),cc.v2(0,1)]);
  82. let samePoints = [];
  83. let newCellStatus = "";
  84. if (rowResult.length >= 5 || colResult.length >= 5){
  85. //任意五个'同行'或'同列'且相同的动物可以合成一个'魔力鸟'特效
  86. newCellStatus = CELL_STATUS.BIRD;
  87. }else if (rowResult.length >= 3 && colResult.length >= 3){
  88. //五个相同的'不同行'动物可以合成一个'爆炸特效'
  89. newCellStatus = CELL_STATUS.WRAP;
  90. }else if (rowResult.length >= 4){
  91. //四个相同的动物一行可以合成一个行直线特效
  92. newCellStatus = CELL_STATUS.LINE;
  93. }else if (colResult.length >= 4){
  94. //四个相同的动物一列可以合成一个列直线特效
  95. newCellStatus = CELL_STATUS.COLUMN;
  96. }
  97. if (rowResult.length >= 3){
  98. samePoints = rowResult;
  99. }
  100. if (colResult.length >= 3){
  101. samePoints = mergePointArray(samePoints, colResult);
  102. }
  103. let result = [samePoints, newCellStatus, this.cells[y][x].type, cc.v2(x, y)];
  104. //检查一下消除的其他节点, 能不能生成更大范围的消除
  105. if (recursive && result.length >= 3){
  106. let subCheckPoints = exclusivePoint(samePoints, cc.v2(x, y));
  107. for (let point of subCheckPoints){
  108. let subResult = this.checkPoint(point.x, point.y, false);
  109. if (subResult[1] > result[1] || (subResult[1] === result[1] && subResult[0].length > result[0].length)){
  110. result = subResult;
  111. }
  112. }
  113. }
  114. return result;
  115. }
  116. checkWithDirection(x, y, direction){
  117. // console.log("direction:",direction)
  118. // console.log("x:",x)
  119. // console.log("y:",y)
  120. let queue = [];
  121. let vis = [];
  122. vis[x + y * 9] = true;
  123. queue.push(cc.v2(x, y));
  124. let front = 0;
  125. while (front < queue.length){
  126. let point = queue[front];
  127. let cellModel = this.cells[point.y][point.x];
  128. front++;
  129. if (!cellModel){
  130. continue;
  131. }
  132. for (let i = 0; i < direction.length; i++){
  133. let tmpX = point.x + direction[i].x;
  134. let tmpY = point.y + direction[i].y;
  135. if (tmpX < 1 || tmpX > 9
  136. || tmpY < 1 || tmpY > 9
  137. || vis[tmpX + tmpY * 9]
  138. || !this.cells[tmpY][tmpX]){
  139. continue;
  140. }
  141. if (cellModel.type === this.cells[tmpY][tmpX].type){
  142. vis[tmpX + tmpY * 9] = true;
  143. queue.push(cc.v2(tmpX, tmpY));
  144. }
  145. }
  146. }
  147. return queue;
  148. }
  149. printInfo(){
  150. for (let i = 1; i <= 9; i++){
  151. let printStr = "";
  152. for (let j = 1; j <= 9; j++){
  153. printStr += this.cells[i][j].type + " ";
  154. }
  155. console.log("printStr:",printStr);
  156. }
  157. }
  158. getCells(){
  159. // console.log(this.cells.length)
  160. // console.log("getCells:",this.cells)
  161. return this.cells;
  162. }
  163. //controller调用的主要入口
  164. //点击某个格子
  165. selectCell(pos){
  166. this.crushNums = 0;
  167. // console.log("当前点击的位置:",pos);
  168. // this.curGridPos = pos;
  169. // console.log("当前点击对象:",this.curGridPos)
  170. this.changeModels = []; //发生改变的model,将作为返回值,给View播动作
  171. this.effectsQueue = []; //动物消失、爆炸等特效
  172. let lastPos = this.lastPos;
  173. let delta = Math.abs(pos.x - lastPos.x) + Math.abs(pos.y - lastPos.y);
  174. // console.log("x轴:",Math.abs(pos.x - lastPos.x))
  175. // console.log("y轴:",Math.abs(pos.y - lastPos.y))
  176. // console.log("delta:",delta)
  177. if (delta != 1){ //非相邻格子,直接返回
  178. this.lastPos = pos;
  179. return [[], []];
  180. }
  181. let curClickCell = this.cells[pos.y][pos.x]; //当前点击的格子
  182. let lastClickCell = this.cells[lastPos.y][lastPos.x]; //上一次点击的格子
  183. // console.log("当前点击的格子:",curClickCell)
  184. // console.log("上一次点击的格子:",lastClickCell)
  185. this.exchangeCell(lastPos, pos);
  186. let result1 = this.checkPoint(pos.x, pos.y)[0];
  187. let result2 = this.checkPoint(lastPos.x, lastPos.y)[0];
  188. // console.log("result1:",result1)
  189. // console.log("result2:",result2)
  190. this.curTime = 0; //动画播放的当前时间
  191. this.pushToChangeModels(curClickCell);
  192. this.pushToChangeModels(lastClickCell);
  193. let isCanBomb = (curClickCell.status != CELL_STATUS.COMMON && //判断两个是否是特殊的动物
  194. lastClickCell.status != CELL_STATUS.COMMON) ||
  195. curClickCell.status == CELL_STATUS.BIRD ||
  196. lastClickCell.status == CELL_STATUS.BIRD;
  197. isCanBomb = curClickCell.status == CELL_STATUS.BIRD || lastClickCell.status == CELL_STATUS.BIRD;
  198. if (result1.length < 3 && result2.length < 3 && !isCanBomb){ //不会发生消除的情况
  199. this.exchangeCell(lastPos, pos);
  200. curClickCell.moveToAndBack(lastPos);
  201. lastClickCell.moveToAndBack(pos);
  202. this.lastPos = cc.v2(-1,-1);
  203. return [this.changeModels];
  204. }else {
  205. // console.log("消除了")
  206. this.lastPos = cc.v2(-1,-1);
  207. curClickCell.moveTo(lastPos, this.curTime);
  208. lastClickCell.moveTo(pos, this.curTime);
  209. let checkPoint = [pos, lastPos];
  210. // console.log("select的checkpoint:",checkPoint)
  211. this.curTime += ANITIME.TOUCH_MOVE;
  212. this.processCrush(checkPoint);
  213. return [this.changeModels,this.effectsQueue];
  214. }
  215. }
  216. //消除
  217. processCrush(checkPoint){
  218. // console.log("消除checkpoint:",checkPoint)
  219. let cycleCount = 0;
  220. while (checkPoint.length > 0){
  221. let bombModels = [];
  222. if (cycleCount == 0 && checkPoint.length == 2){ //特殊消除
  223. let pos1 = checkPoint[0];
  224. let pos2 = checkPoint[1];
  225. let model1 = this.cells[pos1.y][pos1.x];
  226. let model2 = this.cells[pos2.y][pos2.x];
  227. if (model1.status == CELL_STATUS.BIRD || model2.status == CELL_STATUS.BIRD){
  228. let bombModel = null;
  229. if (model1.status == CELL_STATUS.BIRD){
  230. model1.type = model2.type;
  231. bombModels.push(model1);
  232. }else {
  233. model2.type = model1.type;
  234. bombModels.push(model2);
  235. }
  236. }
  237. }
  238. for (let i in checkPoint){
  239. let pos = checkPoint[i];
  240. // console.log("消除中的pos:",pos)
  241. if (!this.cells[pos.y][pos.x]){
  242. continue;
  243. }
  244. let [result, newCellStatus, newCellType, crushPoint] = this.checkPoint(pos.x,pos.y,true);
  245. if (result.length < 3){
  246. continue;
  247. }
  248. for (let j in result){
  249. let model = this.cells[result[j].y][result[j].x];
  250. this.crushCell(result[j].x, result[j].y,false, cycleCount);
  251. if (model.status != CELL_STATUS.COMMON){
  252. bombModels.push(model);
  253. }
  254. }
  255. this.createNewCell(crushPoint, newCellStatus, newCellType);
  256. }
  257. this.processBomb(bombModels,cycleCount);
  258. this.curTime += ANITIME.DIE;
  259. checkPoint = this.down();
  260. // console.log("cccheckPoint:",checkPoint)
  261. // console.log("this.down:",this.down())
  262. cycleCount++;
  263. }
  264. // console.log("消除块数:",this.crushNums)
  265. const playTime = this.effectsQueue[this.effectsQueue.length - 1]["playTime"]
  266. // console.log("playTime:",playTime)
  267. this.addCrushNums(playTime,cc.v2(0,0),this.crushNums)
  268. }
  269. //道具消除一个块
  270. processCrushOne(pos){
  271. // console.log("gmpos:",pos)
  272. this.changeModels = [];
  273. this.effectsQueue = [];
  274. this.curTime = 0;
  275. this.crushNums = 0;
  276. //移除脚本信息
  277. this.crushCell(pos.x,pos.y,false,0);
  278. //时间和计分
  279. const playTime = this.effectsQueue[this.effectsQueue.length - 1]["playTime"]
  280. this.addCrushNums(playTime,cc.v2(0,0),this.crushNums)
  281. // console.log("playTime:",playTime)
  282. //下落
  283. this.down();
  284. // let [result, newCellStatus, newCellType, crushPoint] = this.checkPoint(pos.x,pos.y,true);
  285. // console.log("oneResult:",result)
  286. // this.processCrush(result)
  287. // this.processCrush(this.checkPoint(pos.x,pos.y,true))
  288. let onceArray = [];
  289. for (let i = 1;i <= GRID_WIDTH; i++){
  290. // console.log(i)
  291. for (let j = 1;j <= GRID_HEIGHT; j++){
  292. var [result, newCellStatus, newCellType, crushPoint] = this.checkPoint(i,j,true);
  293. // console.log("oneResult["+i+"]["+j+"]:",result)
  294. if (result.length > 0){
  295. // console.log("if的result:",result)
  296. // this.processCrush(result)
  297. onceArray = mergePointArray(onceArray,result)
  298. }
  299. }
  300. }
  301. this.processCrush(onceArray)
  302. //渲染
  303. return [this.changeModels,this.effectsQueue];
  304. }
  305. // 道具消除整行
  306. processCrushRow(pos){
  307. console.log("pcr:",pos)
  308. // console.log("pcr:",pos.y)
  309. this.changeModels = [];
  310. this.effectsQueue = [];
  311. this.curTime = 0;
  312. this.crushNums = 0;
  313. //循环点击的行的每个格子
  314. for (let i = 1; i <= GRID_WIDTH; i++){
  315. // this.crushCell(i,pos.y,false,0)
  316. this.crushRow(i,pos.y,false,0)
  317. // this.addRowCrush(this.curTime,cc.v2(i,pos.y))
  318. // this.down();
  319. }
  320. // this.addRowCrush(this.curTime,pos)
  321. // let chModel = [];
  322. // console.log("gameModel里的changeModel:",chModel)
  323. // console.log("this.effectsQueue:",this.effectsQueue)
  324. // this.changeModels = chModel
  325. // console.log("重新赋值的changeModels:",this.changeModels)
  326. //时间和计分
  327. const playTime = this.effectsQueue[this.effectsQueue.length - 1]["playTime"]
  328. this.addCrushNums(playTime,cc.v2(0,0),this.crushNums)
  329. // console.log("palyTime:",playTime)
  330. //下落
  331. this.down();
  332. // let [result, newCellStatus, newCellType, crushPoint] = this.checkPoint(pos.x,pos.y,true);
  333. // // console.log("rresult:",result)
  334. // this.processCrush(result)
  335. let onceArray = [];
  336. for (let i = 1;i <= GRID_WIDTH; i++){
  337. // console.log(i)
  338. for (let j = 1;j <= GRID_HEIGHT; j++){
  339. var [result, newCellStatus, newCellType, crushPoint] = this.checkPoint(i,j,true);
  340. // console.log("oneResult["+i+"]["+j+"]:",result)
  341. if (result.length > 0){
  342. // console.log("if的result:",result)
  343. // this.processCrush(result)
  344. onceArray = mergePointArray(onceArray,result)
  345. }
  346. }
  347. }
  348. this.processCrush(onceArray)
  349. //渲染
  350. return [this.changeModels,this.effectsQueue];
  351. }
  352. //道具消除整列
  353. processCrushCol(pos){
  354. // console.log("消除列的pos:",pos)
  355. this.changeModels = [];
  356. this.effectsQueue = [];
  357. this.curTime = 0;
  358. this.crushNums = 0;
  359. //循环点击的列的每个格子
  360. for (let i = 1; i <= GRID_WIDTH; i++){
  361. this.crushCol(pos.x,i,false,0)
  362. }
  363. //时间和计分
  364. const playTime = this.effectsQueue[this.effectsQueue.length - 1]["playTime"]
  365. this.addCrushNums(playTime,cc.v2(0,0),this.crushNums)
  366. // console.log("palyTime:",playTime)
  367. //下落
  368. this.down();
  369. // let [result, newCellStatus, newCellType, crushPoint] = this.checkPoint(pos.x,pos.y,true);
  370. // this.processCrush(result)
  371. let onceArray = [];
  372. for (let i = 1;i <= GRID_WIDTH; i++){
  373. // console.log(i)
  374. for (let j = 1;j <= GRID_HEIGHT; j++){
  375. var [result, newCellStatus, newCellType, crushPoint] = this.checkPoint(i,j,true);
  376. // console.log("oneResult["+i+"]["+j+"]:",result)
  377. if (result.length > 0){
  378. // console.log("if的result:",result)
  379. // this.processCrush(result)
  380. onceArray = mergePointArray(onceArray,result)
  381. }
  382. }
  383. }
  384. this.processCrush(onceArray)
  385. //渲染
  386. return [this.changeModels,this.effectsQueue];
  387. }
  388. //道具消除一种类型的格子
  389. processCrushOneType(pos){
  390. let nowAllCells = this.getCells();
  391. // console.log("nowAllCells:",nowAllCells)
  392. // console.log("长度:",nowAllCells.length)
  393. // console.log("消除一类的pos:",pos)
  394. this.changeModels = [];
  395. this.effectsQueue = [];
  396. this.curTime = 0;
  397. this.crushNums = 0;
  398. let tempModel = [];
  399. let curType = null;
  400. //两层循环,找出当前点击格子的类型
  401. for (let i = 1; i < nowAllCells.length; i++){
  402. // let newArray = nowAllCells[i]
  403. // console.log("newArray:",newArray)
  404. if ( i == pos.y){
  405. // console.log("ii:",i)
  406. for (let j = 1; j < nowAllCells[i].length; j++){
  407. // console.log("nowAllCell["+i+"]"+"["+j+"]:",nowAllCells[i][j])
  408. // console.log("jj:",j)
  409. if (j == pos.x){
  410. // console.log("点击的单元格:",nowAllCells[i][j])
  411. curType = nowAllCells[i][j].type
  412. break;
  413. }
  414. }
  415. break;
  416. }
  417. }
  418. // console.log("curType:",curType)
  419. //再次两层循环,找出与点击格子类型相同的所有格子
  420. for (let i = 1; i < nowAllCells.length; i++){
  421. for (let j = 1; j < nowAllCells[i].length; j++){
  422. // console.log("nowAllCell["+i+"]"+"["+j+"]:",nowAllCells[i][j])
  423. // console.log("类型:",nowAllCells[i][j].type)
  424. if (nowAllCells[i][j].type == curType){
  425. tempModel.push(nowAllCells[i][j])
  426. // console.log("ok")
  427. this.crushOneType(j,i,false,0)
  428. }
  429. }
  430. }
  431. //时间和计分
  432. this.crushNums
  433. const playTime = this.effectsQueue[this.effectsQueue.length - 1]["playTime"]
  434. this.addCrushNums(playTime,cc.v2(0,0),this.crushNums)
  435. // console.log("palyTime:",playTime)
  436. this.changeModels = tempModel;
  437. // console.log("重新赋值的changeModels:",this.changeModels)
  438. //下落
  439. this.down();
  440. // let [result, newCellStatus, newCellType, crushPoint] = this.checkPoint(pos.x,pos.y,true);
  441. // // console.log("消除一类的result:",result)
  442. // this.processCrush(result)
  443. let onceArray = [];
  444. for (let i = 1;i <= GRID_WIDTH; i++){
  445. // console.log(i)
  446. for (let j = 1;j <= GRID_HEIGHT; j++){
  447. var [result, newCellStatus, newCellType, crushPoint] = this.checkPoint(i,j,true);
  448. // console.log("oneResult["+i+"]["+j+"]:",result)
  449. if (result.length > 0){
  450. // console.log("if的result:",result)
  451. onceArray = mergePointArray(onceArray,result)
  452. }
  453. }
  454. }
  455. this.processCrush(onceArray)
  456. //渲染
  457. return [this.changeModels,this.effectsQueue];
  458. }
  459. //生成新cell
  460. createNewCell(pos, status, type){
  461. if (status == ""){
  462. return;
  463. }
  464. if (status == CELL_STATUS.BIRD){
  465. type = CELL_TYPE.BIRD;
  466. }
  467. let model = new CellModel();
  468. this.cells[pos.y][pos.x] = model;
  469. model.init(type);
  470. model.setStartXY(pos.x, pos.y);
  471. model.setXY(pos.x, pos.y);
  472. model.setStatus(status);
  473. model.setVisible(0, false);
  474. model.setVisible(this.curTime, true);
  475. this.changeModels.push(model);
  476. }
  477. //下落
  478. down(){
  479. let newCheckPoint = [];
  480. for (let i = 1; i <= GRID_WIDTH; i++){
  481. for (let j = 1; j <= GRID_HEIGHT; j++){
  482. //找到空位
  483. if (this.cells[i][j] == null){
  484. let curRow = i;
  485. //往上找方块
  486. for (let k = curRow; k <= GRID_HEIGHT; k++){
  487. //找到可用的方块
  488. if (this.cells[k][j]){
  489. // console.log("下落:",this.cells[k][j])
  490. this.pushToChangeModels(this.cells[k][j]);
  491. newCheckPoint.push(this.cells[k][j]);
  492. this.cells[curRow][j] = this.cells[k][j];
  493. this.cells[k][j] = null;
  494. this.cells[curRow][j].setXY(j, curRow);
  495. this.cells[curRow][j].moveTo(cc.v2(j, curRow), this.curTime);
  496. curRow++;
  497. }
  498. }
  499. let count = 1;
  500. for (let k = curRow; k <= GRID_HEIGHT; k++){
  501. this.cells[k][j] = new CellModel();
  502. this.cells[k][j].init(this.getRandomCellType());
  503. this.cells[k][j].setStartXY(j, count + GRID_HEIGHT);
  504. this.cells[k][j].setXY(j, count + GRID_HEIGHT);
  505. this.cells[k][j].moveTo(cc.v2(j, k), this.curTime);
  506. count++;
  507. this.changeModels.push(this.cells[k][j]);
  508. newCheckPoint.push(this.cells[k][j]);
  509. // console.log("xialuo")
  510. }
  511. // console.log("下落的newCheckPoint:",newCheckPoint)
  512. }
  513. }
  514. }
  515. this.curTime += ANITIME.TOUCH_MOVE + 0.3;
  516. return newCheckPoint;
  517. }
  518. pushToChangeModels(model){
  519. if (this.changeModels.indexOf(model) != -1){
  520. return;
  521. }
  522. this.changeModels.push(model);
  523. }
  524. cleanCmd(){
  525. for (let i = 1; i <= GRID_WIDTH; i++){
  526. for (let j = 1; j <= GRID_HEIGHT; j++){
  527. if (this.cells[i][j]){
  528. this.cells[i][j].cmd = [];
  529. }
  530. }
  531. }
  532. }
  533. exchangeCell(pos1, pos2){
  534. let tmpModel = this.cells[pos1.y][pos1.x];
  535. this.cells[pos1.y][pos1.x] = this.cells[pos2.y][pos2.x];
  536. this.cells[pos1.y][pos1.x].x = pos1.x;
  537. this.cells[pos1.y][pos1.x].y = pos1.y;
  538. this.cells[pos2.y][pos2.x] = tmpModel;
  539. this.cells[pos2.y][pos2.x].x = pos2.x;
  540. this.cells[pos2.y][pos2.x].y = pos2.y;
  541. }
  542. //设置种类
  543. //改成乱序算法
  544. setCellTypeNum(num){
  545. // console.log("num = ",num);
  546. this.cellTypeNum = num;
  547. this.cellCreateType = [];
  548. let createTypeList = this.cellCreateType;
  549. for (let i = 1; i <= CELL_BASENUM; i++){
  550. createTypeList.push(i);
  551. }
  552. for (let i = 0; i < createTypeList.length; i++){
  553. let index = Math.floor(Math.random() * (CELL_BASENUM - i)) + i;
  554. createTypeList[i],createTypeList[index] = createTypeList[index],createTypeList[i];
  555. }
  556. }
  557. //随机生成一个类型
  558. getRandomCellType(){
  559. let index = Math.floor(Math.random() * this.cellTypeNum);
  560. // console.log(index)
  561. return this.cellCreateType[index];
  562. }
  563. //bombModels去重
  564. processBomb(bombModels, cycleCount){
  565. // console.log("去重")
  566. // console.log("bombModels:",bombModels)
  567. while (bombModels.length > 0){
  568. let newBombModel = [];
  569. let bombTime = ANITIME.BOMB_DELAY;
  570. bombModels.forEach(function (model) {
  571. if (model.status == CELL_STATUS.LINE){
  572. for (let i = 1; i <= GRID_WIDTH; i++){
  573. if (this.cells[model.y][i]){
  574. if (this.cells[model.y][i].status != CELL_STATUS.COMMON){
  575. newBombModel.push(this.cells[model.y][i]);
  576. }
  577. this.crushCell(i, model.y, false, cycleCount);
  578. }
  579. }
  580. this.addRowBomb(this.curTime, cc.v2(model.x, model.y));
  581. }else if (model.status == CELL_STATUS.COLUMN){
  582. for (let i = 1; i <= GRID_HEIGHT; i++){
  583. if (this.cells[i][model.x]){
  584. if (this.cells[i][model.x].status != CELL_STATUS.COMMON){
  585. newBombModel.push(this.cells[i][model.x]);
  586. }
  587. this.crushCell(model.x, i, false, cycleCount);
  588. }
  589. }
  590. this.addColBomb(this.curTime, cc.v2(model.x, model.y));
  591. }else if (model.status == CELL_STATUS.WRAP){
  592. let x = model.x;
  593. let y = model.y;
  594. for (let i = 1; i <= GRID_HEIGHT; i++){
  595. for (let j = 1; j <= GRID_WIDTH; j++){
  596. let delta = Math.abs(x - j) + Math.abs(y - i);
  597. if (this.cells[i][j] && delta <= 2){
  598. if (this.cells[i][j].status != CELL_STATUS.COMMON){
  599. newBombModel.push(this.cells[i][j]);
  600. }
  601. this.crushCell(j, i, false, cycleCount);
  602. }
  603. }
  604. }
  605. }else if (model.status == CELL_STATUS.BIRD){
  606. let crushType = model.type;
  607. if (bombTime < ANITIME.BOMB_BIRD_DELAY){
  608. bombTime = ANITIME.BOMB_BIRD_DELAY;
  609. }
  610. if (crushType == CELL_STATUS.BIRD){
  611. crushType = this.getRandomCellType();
  612. }
  613. for (let i = 1; i <= GRID_HEIGHT; i++){
  614. for (let j = 1; j <= GRID_WIDTH; j++){
  615. if (this.cells[i][j] && this.cells[i][j].type == crushType){
  616. if (this.cells[i][j].status != CELL_STATUS.COMMON){
  617. newBombModel.push(this.cells[i][j]);
  618. }
  619. this.crushCell(j, i, true, cycleCount);
  620. }
  621. }
  622. }
  623. }
  624. },this)
  625. if (bombModels.length > 0){
  626. this.curTime += bombTime;
  627. }
  628. bombModels = newBombModel;
  629. }
  630. }
  631. /**
  632. *
  633. * @param {*开始播放的时间} playTime
  634. * @param {*cell位置} pos
  635. * @param {*第几次消除,用于播放音效} step
  636. */
  637. //普通消除
  638. addCrushEffect(playTime, pos, step){
  639. this.effectsQueue.push({
  640. playTime,
  641. pos,
  642. action:"crush",
  643. step
  644. });
  645. }
  646. //正常消除整行
  647. addRowBomb(playTime, pos){
  648. this.effectsQueue.push({
  649. playTime,
  650. pos,
  651. action:"rowBomb"
  652. });
  653. }
  654. //道具消除整行
  655. addRowCrush(playTime, pos){
  656. this.effectsQueue.push({
  657. playTime,
  658. pos,
  659. action:"crushRow"
  660. });
  661. }
  662. //道具消除整列
  663. addColCrush(playTime, pos){
  664. this.effectsQueue.push({
  665. playTime,
  666. pos,
  667. action:"crushCol"
  668. });
  669. }
  670. //正常消除整列
  671. addColBomb(playTime, pos){
  672. this.effectsQueue.push({
  673. playTime,
  674. pos,
  675. action:"colBomb"
  676. });
  677. }
  678. addOneTypeCrush(playTime, pos){
  679. this.effectsQueue.push({
  680. playTime,
  681. pos,
  682. action:"typeBomb"
  683. });
  684. }
  685. //分数动画加入队列
  686. addCrushNums(playTime,pos,nums){
  687. this.effectsQueue.push({
  688. playTime,
  689. pos,
  690. action:"crushNums",
  691. nums
  692. });
  693. }
  694. //cell消除逻辑
  695. crushCell(x, y, needShake, step){
  696. let model = this.cells[y][x];
  697. // console.log("crushCellModel:",model)
  698. this.pushToChangeModels(model);
  699. if (needShake){
  700. model.toShake(this.curTime);
  701. }
  702. let shakeTime = needShake ? ANITIME.DIE_SHAKE : 0;
  703. model.toDie(this.curTime + shakeTime);
  704. this.addCrushEffect(this.curTime + shakeTime, cc.v2(model.x,model.y), step);
  705. this.cells[y][x] = null;
  706. this.crushNums++;
  707. // console.log("this.crushNums:",this.crushNums)
  708. }
  709. // 道具消除整行
  710. crushRow(x, y, needShake, step){
  711. let model = this.cells[y][x];
  712. // console.log("crushCellModel:",model)
  713. this.pushToChangeModels(model);
  714. if (needShake){
  715. model.toShake(this.curTime);
  716. }
  717. let shakeTime = needShake ? ANITIME.DIE_SHAKE : 0;
  718. model.toDie(this.curTime + shakeTime);
  719. this.addRowCrush(this.curTime + shakeTime, cc.v2(model.x,model.y), step);
  720. this.cells[y][x] = null;
  721. this.crushNums++;
  722. // console.log("this.crushNums:",this.crushNums)
  723. }
  724. // 道具消除整列
  725. crushCol(x, y, needShake, step){
  726. let model = this.cells[y][x];
  727. // console.log("crushCellModel:",model)
  728. this.pushToChangeModels(model);
  729. if (needShake){
  730. model.toShake(this.curTime);
  731. }
  732. let shakeTime = needShake ? ANITIME.DIE_SHAKE : 0;
  733. model.toDie(this.curTime + shakeTime);
  734. this.addColCrush(this.curTime + shakeTime, cc.v2(model.x,model.y), step);
  735. this.cells[y][x] = null;
  736. this.crushNums++;
  737. // console.log("this.crushNums:",this.crushNums)
  738. }
  739. // 道具消除一种类型
  740. crushOneType(x, y, needShake, step){
  741. let model = this.cells[y][x];
  742. // console.log("crushOneType:",model)
  743. this.pushToChangeModels(model);
  744. if (needShake){
  745. model.toShake(this.curTime);
  746. }
  747. let shakeTime = needShake ? ANITIME.DIE_SHAKE : 0;
  748. model.toDie(this.curTime + shakeTime);
  749. this.addOneTypeCrush(this.curTime + shakeTime, cc.v2(model.x,model.y), step);
  750. this.cells[y][x] = null;
  751. this.crushNums++;
  752. // console.log("this.crushNums:",this.crushNums)
  753. }
  754. }