GameModel.js 32 KB

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