|
|
@@ -2,7 +2,7 @@
|
|
|
* @Author: mojunshou 1637302775@qq.com
|
|
|
* @Date: 2025-03-20 15:01:09
|
|
|
* @LastEditors: mojunshou 1637302775@qq.com
|
|
|
- * @LastEditTime: 2025-03-27 17:40:24
|
|
|
+ * @LastEditTime: 2025-03-27 17:49:05
|
|
|
* @Description: 消除游戏主场景
|
|
|
*/
|
|
|
import { _decorator } from "cc";
|
|
|
@@ -169,6 +169,11 @@ export class EliminateViewComp extends CCComp {
|
|
|
unavailableColor = new Color(255, 0, 0, 100)
|
|
|
//旋转容错
|
|
|
rotateFaultTolerant = 10;
|
|
|
+ private _isAutoFunc: (() => void) | null = null
|
|
|
+
|
|
|
+ isAutoMode: boolean = false;
|
|
|
+ autoModeInterval: number = 1 // 自动模式的间隔时间(秒)
|
|
|
+ autoModeTimer: number = 0 // 自动模式计时器
|
|
|
|
|
|
|
|
|
//网格列表管理列表
|
|
|
@@ -205,6 +210,7 @@ export class EliminateViewComp extends CCComp {
|
|
|
this.initButtonState();
|
|
|
await this.loadConfig();
|
|
|
this.initGrid();
|
|
|
+ this.initData();
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -239,6 +245,12 @@ export class EliminateViewComp extends CCComp {
|
|
|
//初始化数据
|
|
|
private initData() {
|
|
|
this.gameMode = GameMode.MANUAL;
|
|
|
+ this.score = 0;
|
|
|
+ this.money = 0;
|
|
|
+ this.cash = 0;
|
|
|
+ this.lab_score.string = this.score.toString();
|
|
|
+ this.amountLb.string = this.money.toString();
|
|
|
+ this.awardLb.string = this.cash.toString();
|
|
|
}
|
|
|
|
|
|
//初始化网格
|
|
|
@@ -1167,6 +1179,220 @@ export class EliminateViewComp extends CCComp {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ // ... 修改 autoPlaceBrick 方法
|
|
|
+ async autoPlaceBrick() {
|
|
|
+ if (!this.isAutoMode) return;
|
|
|
+ if (this.bricksList.length === 0) return
|
|
|
+
|
|
|
+ // 遍历所有方块,找到一个可以放置的方块
|
|
|
+ let bestMove = null;
|
|
|
+ let selectedBrickIndex = -1;
|
|
|
+
|
|
|
+ for (let i = 0; i < this.bricksList.length; i++) {
|
|
|
+ const move = this.findBestPosition(this.bricksList[i]);
|
|
|
+ if (move) {
|
|
|
+ // 优先选择可以消除的位置
|
|
|
+ if (move.score > 0) {
|
|
|
+ bestMove = move;
|
|
|
+ selectedBrickIndex = i;
|
|
|
+ break;
|
|
|
+ } else if (bestMove === null) {
|
|
|
+ // 如果还没有找到任何可放置的位置,保存这个位置
|
|
|
+ bestMove = move;
|
|
|
+ selectedBrickIndex = i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果所有方块都没有可放置的位置,游戏结束
|
|
|
+ if (!bestMove || selectedBrickIndex === -1) {
|
|
|
+ console.log('所有方块都没有可放置的位置,游戏结束');
|
|
|
+ this.isAutoMode = false;
|
|
|
+ if (this._isAutoFunc) {
|
|
|
+ this.unschedule(this._isAutoFunc);
|
|
|
+ this._isAutoFunc = null;
|
|
|
+ }
|
|
|
+ this.gameOver();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 获取选中的方块
|
|
|
+ const brickData = this.bricksList[selectedBrickIndex];
|
|
|
+ // 从列表中移除方块
|
|
|
+ this.bricksList.splice(selectedBrickIndex, 1);
|
|
|
+ // 保存方块的初始位置(从待选区开始)
|
|
|
+ const startPos = brickData.brickInitPos.clone();
|
|
|
+
|
|
|
+ // 设置方块到移动层并确保位置精确
|
|
|
+ if (brickData.brickNode) {
|
|
|
+ brickData.brickNode.setParent(this.moveNode);
|
|
|
+ brickData.brickNode.setWorldPosition(startPos);
|
|
|
+ }
|
|
|
+
|
|
|
+ // this.guideNode.active = true;
|
|
|
+ // this.guideNode.setWorldPosition(
|
|
|
+ // startPos.x,
|
|
|
+ // startPos.y + brickData.brickNode.getComponent(UITransform).height / 2,
|
|
|
+ // startPos.z
|
|
|
+ // );
|
|
|
+
|
|
|
+ // 如果需要旋转,先旋转到正确的角度
|
|
|
+ if (brickData.rotateFlag && bestMove.rotation && bestMove.rotation.deg !== brickData.deg) {
|
|
|
+ await new Promise<void>((resolve) => {
|
|
|
+ if (brickData.brickNode) {
|
|
|
+ tween(brickData.brickNode)
|
|
|
+ .to(0.2, { angle: bestMove.rotation ? bestMove.rotation.deg : 0 })
|
|
|
+ .call(() => {
|
|
|
+ if (bestMove.rotation) {
|
|
|
+ brickData.gridConfig = bestMove.rotation.gridConfig;
|
|
|
+ brickData.deg = bestMove.rotation.deg;
|
|
|
+ }
|
|
|
+ resolve();
|
|
|
+ })
|
|
|
+ .start();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取目标位置,有些目标位置获取有问题需要修改
|
|
|
+ const targetGrid = this.gridList[bestMove.position.row][bestMove.position.column];
|
|
|
+ if (!targetGrid.gridNode) {
|
|
|
+ console.error('targetGrid.gridNode is null');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const targetWorldPos = targetGrid.gridNode.getWorldPosition().clone();
|
|
|
+
|
|
|
+ // 创建平滑的移动动画
|
|
|
+ await new Promise<void>((resolve) => {
|
|
|
+ if (brickData.brickNode) {
|
|
|
+ tween(brickData.brickNode)
|
|
|
+ .to(0.3, {
|
|
|
+ worldPosition: targetWorldPos,
|
|
|
+ }, {
|
|
|
+ easing: 'cubicOut'
|
|
|
+ })
|
|
|
+ .call(() => {
|
|
|
+ if (brickData.brickNode) {
|
|
|
+ brickData.brickNode.setWorldPosition(targetWorldPos);
|
|
|
+ // 放置方块
|
|
|
+ if (bestMove.rotation) {
|
|
|
+ bestMove.rotation.gridConfig.forEach((gridConfigData) => {
|
|
|
+ const gridData = this.gridList[bestMove.position.row + gridConfigData.row][bestMove.position.column + gridConfigData.column];
|
|
|
+ gridData.status = CellState.FILLED;
|
|
|
+ gridData.gridColorKey = brickData.gridColorKey;
|
|
|
+ gridData.type = brickData.type;
|
|
|
+ this.generateGrid(gridData);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ // 销毁方块
|
|
|
+ brickData.brickNode.destroy();
|
|
|
+ // 添加新方块
|
|
|
+ this.addBrick(brickData.index);
|
|
|
+ }
|
|
|
+ resolve();
|
|
|
+ })
|
|
|
+ .start();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 检查并执行消除
|
|
|
+ await this.gridEliminate();
|
|
|
+
|
|
|
+ // 检查是否还有任何方块可以放置
|
|
|
+ let hasValidMove = false;
|
|
|
+ for (const brick of this.bricksList) {
|
|
|
+ if (this.findBestPosition(brick)) {
|
|
|
+ hasValidMove = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!hasValidMove) {
|
|
|
+ console.log('没有方块可以放置,游戏结束');
|
|
|
+ this.isAutoMode = false;
|
|
|
+ if (this._isAutoFunc) {
|
|
|
+ this.unschedule(this._isAutoFunc);
|
|
|
+ this._isAutoFunc = null;
|
|
|
+ }
|
|
|
+ this.gameOver();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ... 修改 findBestPosition 方法,这个方法有问题,需要修改
|
|
|
+ findBestPosition(brickData: BrickData) {
|
|
|
+ let bestScore = -1
|
|
|
+ let bestPosition = null
|
|
|
+ let bestRotation = null
|
|
|
+
|
|
|
+ let fallbackPosition = null
|
|
|
+ let fallbackRotation = null
|
|
|
+
|
|
|
+ // 遍历所有可能的位置
|
|
|
+ for (let rowIndex = 0; rowIndex < this.rows; rowIndex++) {
|
|
|
+ for (let columnIndex = 0; columnIndex < this.cols; columnIndex++) {
|
|
|
+ // 检查当前位置的所有可能旋转
|
|
|
+ let currentGridConfig = brickData.gridConfig
|
|
|
+ let currentDeg = brickData.deg
|
|
|
+
|
|
|
+ // 最多旋转4次(0°, 90°, 180°, 270°)
|
|
|
+ for (let rotation = 0; rotation < 4; rotation++) {
|
|
|
+ if (this.moveIf(rowIndex, columnIndex, currentGridConfig)) {
|
|
|
+ // 如果还没有找到后备位置,保存第一个可放置的位置
|
|
|
+ if (fallbackPosition === null) {
|
|
|
+ fallbackPosition = { row: rowIndex, column: columnIndex }
|
|
|
+ fallbackRotation = { gridConfig: currentGridConfig, deg: currentDeg }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 模拟放置并计算得分
|
|
|
+ const gridList = this.copyGridList()
|
|
|
+ currentGridConfig.forEach((gridConfigData) => {
|
|
|
+ gridList[gridConfigData.row + rowIndex][gridConfigData.column + columnIndex].status = CellState.FILLED
|
|
|
+ })
|
|
|
+
|
|
|
+ // 计算这个位置的得分
|
|
|
+ const eliminateCheck = this.gridEliminateCheck(gridList)
|
|
|
+ let positionScore = eliminateCheck.gridEliminateList.length
|
|
|
+
|
|
|
+ // 如果这个位置比之前找到的更好
|
|
|
+ if (positionScore > bestScore) {
|
|
|
+ bestScore = positionScore
|
|
|
+ bestPosition = { row: rowIndex, column: columnIndex }
|
|
|
+ bestRotation = { gridConfig: currentGridConfig, deg: currentDeg }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 如果方块可以旋转,计算下一个旋转状态
|
|
|
+ if (brickData.rotateFlag && rotation < 3) {
|
|
|
+ const next = this.nextGridRotate(currentGridConfig, currentDeg)
|
|
|
+ currentGridConfig = next.gridConfig
|
|
|
+ currentDeg = next.deg
|
|
|
+ } else {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果找到了最佳得分位置,返回它
|
|
|
+ if (bestPosition !== null) {
|
|
|
+ return {
|
|
|
+ position: bestPosition,
|
|
|
+ rotation: bestRotation,
|
|
|
+ score: bestScore
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果没有找到可消除的位置但有可放置的位置,返回第一个可放置的位置
|
|
|
+ if (fallbackPosition !== null) {
|
|
|
+ return {
|
|
|
+ position: fallbackPosition,
|
|
|
+ rotation: fallbackRotation,
|
|
|
+ score: 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果真的没有任何可放置的位置,返回null
|
|
|
+ return null
|
|
|
+ }
|
|
|
+
|
|
|
//========================打开其他界面和按钮逻辑=======================
|
|
|
|
|
|
/** 视图对象通过 ecs.Entity.remove(eliminateViewComp) 删除组件是触发组件处理自定义释放逻辑 */
|
|
|
@@ -1183,7 +1409,29 @@ export class EliminateViewComp extends CCComp {
|
|
|
this.autoClick = false;
|
|
|
break;
|
|
|
}
|
|
|
- console.log("自动点击状态:", this.autoClick);
|
|
|
+ this.startAutoMode();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private startAutoMode() {
|
|
|
+ if (
|
|
|
+ this.gameState !== GameState.READY ||
|
|
|
+ this.editingFlag
|
|
|
+ ) return
|
|
|
+ // 切换自动模式状态
|
|
|
+ this.isAutoMode = this.autoClick;
|
|
|
+ if (this.isAutoMode) {
|
|
|
+ this._isAutoFunc = () => {
|
|
|
+ this.autoPlaceBrick()
|
|
|
+ }
|
|
|
+ this.schedule(this._isAutoFunc, this.autoModeInterval)
|
|
|
+ } else {
|
|
|
+ if (this._isAutoFunc) {
|
|
|
+ this.unschedule(this._isAutoFunc)
|
|
|
+ this._isAutoFunc = null
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
|