GameModel.js 32 KB

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