BlockLink.ts 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. import { _decorator, BoxCollider, Color, Component, Graphics, instantiate, Label, Node, Prefab, sp, Sprite, SpriteFrame, tween, v3, Vec3 } from 'cc';
  2. import { Block } from './Block';
  3. import { BlockUtil } from './BlockUitl';
  4. import { blockMap } from './blockMap';
  5. import { LvDir } from '../../LvData/LvData';
  6. const { ccclass, property } = _decorator;
  7. @ccclass('BlockLink')
  8. export class BlockLink extends Component {
  9. mapConfig: blockMap = new blockMap();
  10. // 记录选择的两个方块
  11. public selectedBlocks: Node[] = [];
  12. @property(Graphics)
  13. lineGraphics: Graphics | null = null; // 绘制连线的Graphics组件
  14. lineNode//连线节点
  15. @property(sp.Skeleton)
  16. lianSkeleton: sp.Skeleton | null = null;//绘制连线的骨骼
  17. @property(Prefab)
  18. lineSegmentPrefab: Prefab | null = null; // 线段骨骼预制
  19. @property({ type: sp.SkeletonData })
  20. spineData: sp.SkeletonData | null = null;
  21. spineRefLength: number = 70; // 骨骼动画原始长度
  22. // 存储所有方块节点
  23. static blockArry: (Node | null)[][] = [];
  24. //当前选择的方块
  25. public sleeBlock: Node = null;
  26. public static totalBlocks: number = 0;
  27. public static remainingBlocks: number = 0;
  28. // 匹配锁定
  29. public isMatching: boolean = false;
  30. public isMoving: boolean = false;
  31. static inti: BlockLink
  32. start() {
  33. BlockLink.inti = this;
  34. this.node.getChildByName("line").active = false
  35. this.isMoving = false
  36. this.isMatching = false;
  37. }
  38. isConnected(block1: Node, block2: Node, isSearch = false): boolean {
  39. if (!this.node.isValid) return;
  40. //debugger
  41. this.selectedBlocks = [block1, block2];
  42. // 直连(最快)
  43. const isLineConnected = this.isLineConnected(block1, block2);
  44. console.log(`是否直连: ${isLineConnected}`);
  45. if (isLineConnected) {
  46. if (!this.node.isValid) return;
  47. if (!isSearch) {
  48. const block1Comp = block1.getComponent(Block);
  49. const block2Comp = block2.getComponent(Block);
  50. if (block1Comp && block2Comp) {
  51. this.drawDirectLine(block2, block1);
  52. block1Comp.handleMatchSuccess(block2Comp);
  53. }
  54. }
  55. return true;
  56. }
  57. // 再检查一个拐点
  58. const isOneLinkcrease = this.isOneLinkcrease(block1, block2);
  59. console.log(`是否一个拐点连接: ${isOneLinkcrease}`);
  60. if (isOneLinkcrease) {
  61. if (!this.node.isValid) return;
  62. if (!isSearch) {
  63. const block1Comp = block1.getComponent(Block);
  64. const block2Comp = block2.getComponent(Block);
  65. if (block1Comp && block2Comp) {
  66. // 获取拐点世界坐标
  67. const cornerPos = this.getLinkCorner(block1, block2);
  68. if (cornerPos) {
  69. this.drawPathWithCorner(block2, cornerPos, block1);
  70. // 绘制路径时使用:起点 -> cornerPos -> 终点
  71. } else {
  72. console.log("没有找到有效拐点路径");
  73. }
  74. block1Comp.handleMatchSuccess(block2Comp);
  75. }
  76. }
  77. return true;
  78. }
  79. // 两个拐点(最慢)
  80. const istwoLinkcrease = this.istwoLinkcrease(block1, block2);
  81. console.log(`是否两个拐点连接: ${istwoLinkcrease}`);
  82. if (istwoLinkcrease) {
  83. if (!this.node.isValid) return;
  84. if (!isSearch) {
  85. const block1Comp = block1.getComponent(Block);
  86. const block2Comp = block2.getComponent(Block);
  87. if (block1Comp && block2Comp) {
  88. // 新增:获取两个拐点坐标
  89. const start = this.getBlockPosition(block1);
  90. const end = this.getBlockPosition(block2);
  91. const corners = BlockUtil.getTwoLinkCorners(
  92. start.row, start.col,
  93. end.row, end.col,
  94. this.mapConfig.rows, this.mapConfig.cols,
  95. (row, col) => this.canPass(row, col)
  96. );
  97. if (corners) {
  98. // 将行列坐标转换为世界坐标
  99. const corner1Pos = v3(
  100. this.mapConfig.gridOrigin.x + corners[0].j * this.mapConfig.spacing,
  101. this.mapConfig.gridOrigin.y - corners[0].i * this.mapConfig.spacing,
  102. 0
  103. );
  104. const corner2Pos = v3(
  105. this.mapConfig.gridOrigin.x + corners[1].j * this.mapConfig.spacing,
  106. this.mapConfig.gridOrigin.y - corners[1].i * this.mapConfig.spacing,
  107. 0
  108. );
  109. // 绘制双拐点路径(需先实现 drawPathWithTwoCorners 方法)
  110. this.drawPathWithTwoCorners(block2, corner2Pos, corner1Pos, block1);
  111. }
  112. block1Comp.handleMatchSuccess(block2Comp);
  113. }
  114. }
  115. return true;
  116. }
  117. }
  118. isLineConnected(block1: Node, block2: Node): boolean {
  119. if (!this.node.isValid) return;
  120. //debugger
  121. console.log("直线")
  122. const start = this.getBlockPosition(block1)
  123. const end = this.getBlockPosition(block2)
  124. return BlockUtil.isLineConnectedByIndex(
  125. start.row, start.col, end.row, end.col,
  126. (row, col) => this.canPass(row, col)
  127. );
  128. }
  129. isOneLinkcrease(block1: Node, block2: Node): boolean {
  130. if (!this.node.isValid) return;
  131. //debugger
  132. console.log("1个折角")
  133. const start = this.getBlockPosition(block1)
  134. const end = this.getBlockPosition(block2)
  135. return BlockUtil.isOneLink(
  136. start.row, start.col, end.row, end.col,
  137. (row, col) => this.canPass(row, col)
  138. );
  139. }
  140. istwoLinkcrease(block1: Node, block2: Node): boolean {
  141. if (!this.node.isValid) return;
  142. //debugger
  143. console.log("两个折角")
  144. const start = this.getBlockPosition(block1)
  145. const end = this.getBlockPosition(block2)
  146. return BlockUtil.isTwoLink(
  147. start.row, start.col, end.row, end.col,
  148. this.mapConfig.rows, this.mapConfig.cols,
  149. (row, col) => this.canPass(row, col)
  150. );
  151. }
  152. canPass(_row: number, _col: number): boolean {
  153. //debugger;
  154. // 检查边界外的位置
  155. if (_row < 0 || _row >= this.mapConfig.rows || _col < 0 || _col >= this.mapConfig.cols) {
  156. //console.log(`位置 (${_row}, ${_col}) 超出边界`);
  157. return true;
  158. }
  159. // 明确区分起点终点检查
  160. const isStart = this.isSameBlock(_row, _col, this.selectedBlocks[0]);
  161. const isEnd = this.isSameBlock(_row, _col, this.selectedBlocks[1]);
  162. if (isStart) {
  163. return true;
  164. }
  165. if (isEnd) {
  166. return true;
  167. }
  168. // 检查空位
  169. const isEmpty = BlockLink.blockArry[_row][_col] === null;
  170. if (!isEmpty) {
  171. // console.log(`位置 (${_row}, ${_col}) 已被占用。`);
  172. return false;
  173. }
  174. //console.log(`位置 (${_row}, ${_col}) 可以通过。`);
  175. return true;
  176. }
  177. // 判断指定行列位置是否是某个方块
  178. private isSameBlock(_row: number, _col: number, block: Node): boolean {
  179. //debugger
  180. if (!block) return false;
  181. const pos = this.getBlockPosition(block);
  182. return pos.row === _row && pos.col === _col;
  183. }
  184. //获取行列
  185. public getRowCol(pos: Vec3): { i: number, j: number } {
  186. // debugger
  187. const offsetX = pos.x - this.mapConfig.gridOrigin.x;
  188. const offsetY = this.mapConfig.gridOrigin.y - pos.y;
  189. const j = Math.round(offsetX / this.mapConfig.spacing);
  190. const i = Math.round(offsetY / this.mapConfig.spacing);
  191. if (i < 0 || i >= this.mapConfig.rows || j < 0 || j >= this.mapConfig.cols) {
  192. console.log(`坐标转换: (${pos.x}, ${pos.y}) -> (${i}, ${j})`);
  193. }
  194. console.log(`getRowCol行: ${i}, 列: ${j}`)
  195. return { i, j };
  196. }
  197. getBlockPosition(blockNode: Node) {
  198. for (let row = 0; row < this.mapConfig.rows; row++) {
  199. for (let col = 0; col < this.mapConfig.cols; col++) {
  200. if (BlockLink.blockArry[row][col] === blockNode) {
  201. return { row, col }; // 正确返回行列
  202. }
  203. }
  204. }
  205. return null;
  206. }
  207. getLinkCorner(block1: Node, block2: Node): Vec3 | null {
  208. const start = this.getBlockPosition(block1);
  209. const end = this.getBlockPosition(block2);
  210. const corner = BlockUtil.getOneLinkCorner(
  211. start.row, start.col,
  212. end.row, end.col,
  213. (row, col) => this.canPass(row, col)
  214. );
  215. if (!corner) return null;
  216. // 将行列坐标转换为世界坐标
  217. return v3(
  218. this.mapConfig.gridOrigin.x + corner.j * this.mapConfig.spacing,
  219. this.mapConfig.gridOrigin.y - corner.i * this.mapConfig.spacing,
  220. 0
  221. );
  222. }
  223. /**
  224. * 绘制两个方块的直连路径
  225. * @param startNode 起点方块节点
  226. * @param endNode 终点方块节点
  227. */
  228. private drawDirectLine(startNode: Node, endNode: Node): void {
  229. const graphics = this.node.getChildByName("Graphics").getComponent(Graphics);
  230. graphics.node.setSiblingIndex(graphics.node.parent.children.length - 1); // 置顶
  231. graphics.clear();
  232. // graphics.fillColor.fromHEX('#0000FF');
  233. // graphics.fillColor.fromHEX('#ff0000');
  234. // graphics.fillColor = new Color().fromHEX('#0000ff');
  235. let fillColor = new Color().fromHEX('#3562ff')
  236. graphics.strokeColor = fillColor
  237. graphics.lineWidth = 12;
  238. const startPos = startNode.position;
  239. const endPos = endNode.position;
  240. // 绘制直线路径
  241. graphics.moveTo(startPos.x, startPos.y);
  242. graphics.lineTo(endPos.x, endPos.y);
  243. graphics.stroke();
  244. this.scheduleOnce(() => {
  245. graphics.clear();
  246. console.log("路径已清除");
  247. }, 0.35);
  248. }
  249. /**
  250. * 绘制从起点到拐点再到终点的折线
  251. * @param startNode 起点方块节点
  252. * @param cornerPos 拐点世界坐标
  253. * @param endNode 终点方块节点
  254. */
  255. private drawPathWithCorner(startNode: Node, cornerPos: Vec3, endNode: Node): void {
  256. const graphics = this.node.getChildByName("Graphics").getComponent(Graphics);
  257. graphics.node.setSiblingIndex(graphics.node.parent.children.length - 1); // 置顶
  258. graphics.clear();
  259. //graphics.strokeColor = Color.BLUE;
  260. // graphics.fillColor.fromHEX('#0000FF')
  261. //graphics.fillColor = new Color().fromHEX('#0000ff');
  262. let fillColor = new Color().fromHEX('#3562ff')
  263. graphics.strokeColor = fillColor
  264. graphics.lineWidth = 12;
  265. // 增强调试输出
  266. const startPos = startNode.position;
  267. const endPos = endNode.position;
  268. const cornerWorldPos = cornerPos.clone(); // 已经是世界坐标
  269. // 绘制路径
  270. graphics.moveTo(startPos.x, startPos.y);
  271. graphics.lineTo(cornerWorldPos.x, cornerWorldPos.y); // 直接到拐点
  272. graphics.lineTo(endPos.x, endPos.y); // 再到终点
  273. graphics.stroke();
  274. this.scheduleOnce(() => {
  275. graphics.clear();
  276. console.log("路径已清除");
  277. }, 0.5);
  278. }
  279. /**
  280. * 绘制带两个拐点的路径
  281. * @param startNode 起点节点
  282. * @param corner1Pos 第一个拐点世界坐标
  283. * @param corner2Pos 第二个拐点世界坐标
  284. * @param endNode 终点节点
  285. */
  286. private drawPathWithTwoCorners(
  287. startNode: Node,
  288. corner1Pos: Vec3,
  289. corner2Pos: Vec3,
  290. endNode: Node
  291. ): void {
  292. const graphics = this.node.getChildByName("Graphics").getComponent(Graphics);
  293. graphics.node.setSiblingIndex(graphics.node.parent.children.length - 1); // 置顶
  294. graphics.clear();
  295. //graphics.fillColor.fromHEX('#0000FF');
  296. graphics.lineWidth = 12;
  297. // graphics.color = Color.BLUE;
  298. let fillColor = new Color().fromHEX('#3562ff')
  299. graphics.strokeColor = fillColor
  300. const startPos = startNode.position;
  301. const endPos = endNode.position;
  302. // 绘制路径
  303. graphics.moveTo(startPos.x, startPos.y);
  304. graphics.lineTo(corner1Pos.x, corner1Pos.y);
  305. graphics.lineTo(corner2Pos.x, corner2Pos.y);
  306. graphics.lineTo(endPos.x, endPos.y);
  307. graphics.stroke();
  308. this.scheduleOnce(() => {
  309. graphics.clear();
  310. console.log("路径已清除");
  311. }, 0.5);
  312. }
  313. // /**方块移动*/
  314. // BlockLink.ts
  315. public moveByLevelDirection(lvDir: LvDir): void {
  316. switch (lvDir) {
  317. case LvDir.left:
  318. this.moveAllLeft();
  319. break;
  320. case LvDir.right:
  321. this.moveAllRight();
  322. break;
  323. case LvDir.up:
  324. this.moveAllUp();
  325. break;
  326. case LvDir.down:
  327. this.moveAllDown();
  328. break;
  329. case LvDir.xCenter:
  330. this.moveToCenter(true);
  331. break;
  332. case LvDir.xOut:
  333. this.moveFromCenter(false);
  334. break;
  335. case LvDir.yCenter:
  336. this.moveToCenter(false);
  337. break;
  338. case LvDir.yOut:
  339. this.moveFromCenter(true);
  340. break;
  341. }
  342. }
  343. private moveAllLeft() {
  344. this.isMoving = true;
  345. for (let row = 0; row < this.mapConfig.rows; row++) {
  346. const originalRow = [...BlockLink.blockArry[row]];
  347. const rowBlocks = originalRow.filter(block => block !== null);
  348. const newRow = new Array(this.mapConfig.cols).fill(null);
  349. for (let i = 0; i < rowBlocks.length; i++) {
  350. newRow[i] = rowBlocks[i];
  351. }
  352. BlockLink.blockArry[row] = newRow;
  353. for (let col = 0; col < this.mapConfig.cols; col++) {
  354. const block = BlockLink.blockArry[row][col];
  355. if (block) {
  356. const newX = this.mapConfig.gridOrigin.x + col * this.mapConfig.spacing;
  357. const newY = this.mapConfig.gridOrigin.y - row * this.mapConfig.spacing;
  358. tween(block)
  359. .to(0.2, { position: v3(newX, newY, 0) })
  360. .call(() => {
  361. this.isMoving = false;
  362. })
  363. .start();
  364. }
  365. }
  366. }
  367. }
  368. private moveAllRight() {
  369. this.isMoving = true;
  370. for (let row = 0; row < this.mapConfig.rows; row++) {
  371. const originalRow = [...BlockLink.blockArry[row]];
  372. const blocksInRow = originalRow.filter(block => block !== null);
  373. const startCol = this.mapConfig.cols - blocksInRow.length;
  374. const newRow = new Array(this.mapConfig.cols).fill(null);
  375. for (let i = 0; i < blocksInRow.length; i++) {
  376. newRow[startCol + i] = blocksInRow[i];
  377. }
  378. BlockLink.blockArry[row] = newRow;
  379. for (let col = 0; col < this.mapConfig.cols; col++) {
  380. const block = BlockLink.blockArry[row][col];
  381. if (block) {
  382. const newX = this.mapConfig.gridOrigin.x + col * this.mapConfig.spacing;
  383. const newY = this.mapConfig.gridOrigin.y - row * this.mapConfig.spacing;
  384. tween(block)
  385. .to(0.2, { position: v3(newX, newY, 0) })
  386. .call(() => {
  387. this.isMoving = false;
  388. })
  389. .start();
  390. }
  391. }
  392. }
  393. }
  394. /**上移 */
  395. private moveAllUp() {
  396. this.isMoving = true;
  397. for (let col = 0; col < this.mapConfig.cols; col++) {
  398. const blocksInCol = BlockLink.blockArry.map(row => row[col]).filter(block => block !== null);
  399. BlockLink.blockArry.forEach(row => row[col] = null);
  400. const startRow = 0;
  401. for (let row = 0; row < blocksInCol.length; row++) {
  402. const block = blocksInCol[row];
  403. BlockLink.blockArry[startRow + row][col] = block;
  404. const newX = this.mapConfig.gridOrigin.x + col * this.mapConfig.spacing;
  405. const newY = this.mapConfig.gridOrigin.y - (startRow + row) * this.mapConfig.spacing;
  406. tween(block)
  407. .to(0.2, { position: v3(newX, newY, 0) })
  408. .call(() => {
  409. this.isMoving = false;
  410. })
  411. .start();
  412. }
  413. }
  414. }
  415. /**下移 */
  416. private moveAllDown() {
  417. this.isMoving = true;
  418. for (let col = 0; col < this.mapConfig.cols; col++) {
  419. const blocksInCol = BlockLink.blockArry.map(row => row[col]).filter(block => block !== null);
  420. BlockLink.blockArry.forEach(row => row[col] = null);
  421. const startRow = this.mapConfig.rows - blocksInCol.length;
  422. for (let row = 0; row < blocksInCol.length; row++) {
  423. const block = blocksInCol[row];
  424. BlockLink.blockArry[startRow + row][col] = block;
  425. const newX = this.mapConfig.gridOrigin.x + col * this.mapConfig.spacing;
  426. const newY = this.mapConfig.gridOrigin.y - (startRow + row) * this.mapConfig.spacing;
  427. tween(block)
  428. .to(0.2, { position: v3(newX, newY, 0) })
  429. .call(() => {
  430. this.isMoving = false;
  431. })
  432. .start();
  433. }
  434. }
  435. }
  436. /** 移动到中心 */
  437. private moveToCenter(isHorizontal: boolean) {
  438. this.isMoving = true;
  439. if (isHorizontal) {
  440. for (let row = 0; row < this.mapConfig.rows; row++) {
  441. const blocks = BlockLink.blockArry[row].filter(b => b !== null);
  442. const startCol = Math.floor((this.mapConfig.cols - blocks.length) / 2);
  443. BlockLink.blockArry[row].fill(null);
  444. blocks.forEach((block, idx) => {
  445. const targetCol = startCol + idx;
  446. BlockLink.blockArry[row][targetCol] = block;
  447. const newX = this.mapConfig.gridOrigin.x + targetCol * this.mapConfig.spacing;
  448. const newY = this.mapConfig.gridOrigin.y - row * this.mapConfig.spacing;
  449. tween(block)
  450. .to(0.2, { position: v3(newX, newY, 0) })
  451. .call(() => {
  452. this.isMoving = false;
  453. })
  454. .start();
  455. });
  456. }
  457. } else {
  458. for (let col = 0; col < this.mapConfig.cols; col++) {
  459. const blocks = BlockLink.blockArry.map(row => row[col]).filter(b => b !== null);
  460. const startRow = Math.floor((this.mapConfig.rows - blocks.length) / 2);
  461. BlockLink.blockArry.forEach(row => row[col] = null);
  462. blocks.forEach((block, idx) => {
  463. const targetRow = startRow + idx;
  464. BlockLink.blockArry[targetRow][col] = block;
  465. const newX = this.mapConfig.gridOrigin.x + col * this.mapConfig.spacing;
  466. const newY = this.mapConfig.gridOrigin.y - targetRow * this.mapConfig.spacing;
  467. tween(block)
  468. .to(0.2, { position: v3(newX, newY, 0) })
  469. .call(() => {
  470. this.isMoving = false;
  471. })
  472. .start();
  473. });
  474. }
  475. }
  476. }
  477. /** 从中心移出 */
  478. private moveFromCenter(isHorizontal: boolean) {
  479. this.isMoving = true;
  480. if (isHorizontal) {
  481. for (let row = 0; row < this.mapConfig.rows; row++) {
  482. const leftBlocks = [];
  483. const rightBlocks = [];
  484. const centerCol = Math.floor(this.mapConfig.cols / 2);
  485. for (let col = 0; col < centerCol; col++) {
  486. if (BlockLink.blockArry[row][col]) {
  487. leftBlocks.push({ block: BlockLink.blockArry[row][col], originalCol: col });
  488. }
  489. }
  490. for (let col = centerCol; col < this.mapConfig.cols; col++) {
  491. if (BlockLink.blockArry[row][col]) {
  492. rightBlocks.push({ block: BlockLink.blockArry[row][col], originalCol: col });
  493. }
  494. }
  495. BlockLink.blockArry[row].fill(null);
  496. leftBlocks.sort((a, b) => a.originalCol - b.originalCol);
  497. for (let i = 0; i < leftBlocks.length; i++) {
  498. const block = leftBlocks[i].block;
  499. const targetCol = i;
  500. BlockLink.blockArry[row][targetCol] = block;
  501. const newX = this.mapConfig.gridOrigin.x + targetCol * this.mapConfig.spacing;
  502. const newY = this.mapConfig.gridOrigin.y - row * this.mapConfig.spacing;
  503. tween(block)
  504. .to(0.2, { position: v3(newX, newY, 0) })
  505. .call(() => {
  506. this.isMoving = false;
  507. })
  508. .start();
  509. }
  510. rightBlocks.sort((a, b) => b.originalCol - a.originalCol);
  511. for (let i = 0; i < rightBlocks.length; i++) {
  512. const block = rightBlocks[i].block;
  513. const targetCol = this.mapConfig.cols - 1 - i;
  514. BlockLink.blockArry[row][targetCol] = block;
  515. const newX = this.mapConfig.gridOrigin.x + targetCol * this.mapConfig.spacing;
  516. const newY = this.mapConfig.gridOrigin.y - row * this.mapConfig.spacing;
  517. tween(block)
  518. .to(0.2, { position: v3(newX, newY, 0) })
  519. .call(() => {
  520. this.isMoving = false;
  521. })
  522. .start();
  523. }
  524. }
  525. } else {
  526. for (let col = 0; col < this.mapConfig.cols; col++) {
  527. const topBlocks = [];
  528. const bottomBlocks = [];
  529. for (let row = 0; row < 5; row++) {
  530. if (BlockLink.blockArry[row][col]) {
  531. topBlocks.push({ block: BlockLink.blockArry[row][col], originalRow: row });
  532. }
  533. }
  534. for (let row = 5; row < this.mapConfig.rows; row++) {
  535. if (BlockLink.blockArry[row][col]) {
  536. bottomBlocks.push({ block: BlockLink.blockArry[row][col], originalRow: row });
  537. }
  538. }
  539. BlockLink.blockArry.forEach(row => row[col] = null);
  540. topBlocks.sort((a, b) => a.originalRow - b.originalRow);
  541. for (let i = 0; i < topBlocks.length; i++) {
  542. const block = topBlocks[i].block;
  543. const targetRow = i;
  544. BlockLink.blockArry[targetRow][col] = block;
  545. const newX = this.mapConfig.gridOrigin.x + col * this.mapConfig.spacing;
  546. const newY = this.mapConfig.gridOrigin.y - targetRow * this.mapConfig.spacing;
  547. tween(block)
  548. .to(0.2, { position: v3(newX, newY, 0) })
  549. .call(() => {
  550. this.isMoving = false;
  551. })
  552. .start();
  553. }
  554. bottomBlocks.sort((a, b) => b.originalRow - a.originalRow);
  555. for (let i = 0; i < bottomBlocks.length; i++) {
  556. const block = bottomBlocks[i].block;
  557. const targetRow = this.mapConfig.rows - 1 - i;
  558. BlockLink.blockArry[targetRow][col] = block;
  559. const newX = this.mapConfig.gridOrigin.x + col * this.mapConfig.spacing;
  560. const newY = this.mapConfig.gridOrigin.y - targetRow * this.mapConfig.spacing;
  561. tween(block)
  562. .to(0.2, { position: v3(newX, newY, 0) })
  563. .call(() => {
  564. this.isMoving = false;
  565. })
  566. .start();
  567. }
  568. }
  569. }
  570. }
  571. }