|
@@ -2,7 +2,7 @@
|
|
|
* @Author: mojunshou 1637302775@qq.com
|
|
* @Author: mojunshou 1637302775@qq.com
|
|
|
* @Date: 2025-03-20 15:01:09
|
|
* @Date: 2025-03-20 15:01:09
|
|
|
* @LastEditors: mojunshou 1637302775@qq.com
|
|
* @LastEditors: mojunshou 1637302775@qq.com
|
|
|
- * @LastEditTime: 2025-04-11 11:27:37
|
|
|
|
|
|
|
+ * @LastEditTime: 2025-04-11 15:59:26
|
|
|
* @Description: 消除游戏主场景
|
|
* @Description: 消除游戏主场景
|
|
|
*/
|
|
*/
|
|
|
import { _decorator, Button, Color, EventTouch, instantiate, JsonAsset, Label, Node, Prefab, randomRangeInt, Sprite, tween, UITransform, Vec2, Vec3, Widget } from "cc";
|
|
import { _decorator, Button, Color, EventTouch, instantiate, JsonAsset, Label, Node, Prefab, randomRangeInt, Sprite, tween, UITransform, Vec2, Vec3, Widget } from "cc";
|
|
@@ -27,12 +27,6 @@ enum GameState {
|
|
|
GAME_OVER // 游戏结束
|
|
GAME_OVER // 游戏结束
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// 游戏模式枚举
|
|
|
|
|
-enum GameMode {
|
|
|
|
|
- MANUAL, // 手动模式
|
|
|
|
|
- AUTO // 自动模式
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
|
|
|
|
|
// 格子状态
|
|
// 格子状态
|
|
|
enum CellState {
|
|
enum CellState {
|
|
@@ -41,16 +35,6 @@ enum CellState {
|
|
|
HIGHLIGHTED // 高亮(可放置)
|
|
HIGHLIGHTED // 高亮(可放置)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// 新手引导步骤
|
|
|
|
|
-enum TutorialStep {
|
|
|
|
|
- NONE, // 无引导
|
|
|
|
|
- ROW_ELIMINATION, // 行消除引导
|
|
|
|
|
- COLUMN_ELIMINATION, // 列消除引导
|
|
|
|
|
- ROTATION, // 旋转引导
|
|
|
|
|
- FINAL_ELIMINATION // 最终消除引导
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
//网格数据接口
|
|
//网格数据接口
|
|
|
interface GridData {
|
|
interface GridData {
|
|
|
name: string, // 名称
|
|
name: string, // 名称
|
|
@@ -171,7 +155,7 @@ export class EliminateViewComp extends CCComp {
|
|
|
isAutoMode: boolean = false;
|
|
isAutoMode: boolean = false;
|
|
|
autoModeInterval: number = 1 // 自动模式的间隔时间(秒)
|
|
autoModeInterval: number = 1 // 自动模式的间隔时间(秒)
|
|
|
autoModeTimer: number = 0 // 自动模式计时器
|
|
autoModeTimer: number = 0 // 自动模式计时器
|
|
|
-
|
|
|
|
|
|
|
+ adShowingFlag: boolean = false;
|
|
|
|
|
|
|
|
//网格列表管理列表
|
|
//网格列表管理列表
|
|
|
gridList: GridData[][] = [];
|
|
gridList: GridData[][] = [];
|
|
@@ -219,7 +203,8 @@ export class EliminateViewComp extends CCComp {
|
|
|
addEventList() {
|
|
addEventList() {
|
|
|
oops.message.on(GameEvent.RestartGame, this.restartGame, this);
|
|
oops.message.on(GameEvent.RestartGame, this.restartGame, this);
|
|
|
oops.message.on(GameEvent.DoubleSpeedOpenSuccess, this.doubleSpeedOpenSuccess, this);
|
|
oops.message.on(GameEvent.DoubleSpeedOpenSuccess, this.doubleSpeedOpenSuccess, this);
|
|
|
- oops.message.on(GameEvent.openView, this.openView, this)
|
|
|
|
|
|
|
+ oops.message.on(GameEvent.openView, this.openView, this);
|
|
|
|
|
+ oops.message.on(GameEvent.showCoinAnimation, this.showCoinAnimation, this);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -287,10 +272,48 @@ export class EliminateViewComp extends CCComp {
|
|
|
case "openPassView":
|
|
case "openPassView":
|
|
|
oops.gui.open(UIID.GamePass);
|
|
oops.gui.open(UIID.GamePass);
|
|
|
break;
|
|
break;
|
|
|
|
|
+ case "openDoubleSurprise":
|
|
|
|
|
+ oops.gui.open(UIID.DoubleRewards);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case "openRebateView":
|
|
|
|
|
+ oops.gui.open(UIID.CashRebate);
|
|
|
|
|
+ break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+ //显示金币动画
|
|
|
|
|
+ showCoinAnimation(event: string, args: string) {
|
|
|
|
|
+ //计算中间的坐标就好
|
|
|
|
|
+ const lastPos = this.moveNode.getWorldPosition();
|
|
|
|
|
+ const score = this.score;
|
|
|
|
|
+
|
|
|
|
|
+ // 添加回调函数,在金币动画完成后显示微信分数增加
|
|
|
|
|
+ this.createCoinFlyAnimation(
|
|
|
|
|
+ this.coinPrefab,
|
|
|
|
|
+ lastPos,
|
|
|
|
|
+ this.amountLb.node.getWorldPosition(),
|
|
|
|
|
+ score,
|
|
|
|
|
+ () => {
|
|
|
|
|
+ // 显示微信分数增加动画
|
|
|
|
|
+ this.showWechatScoreAnimation();
|
|
|
|
|
+ }
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ // 添加回调函数,在红包动画完成后显示红包分数增加
|
|
|
|
|
+ this.createCoinFlyAnimation(
|
|
|
|
|
+ this.redPacketPrefab,
|
|
|
|
|
+ lastPos,
|
|
|
|
|
+ this.awardLb.node.getWorldPosition(),
|
|
|
|
|
+ 5,
|
|
|
|
|
+ () => {
|
|
|
|
|
+ // 显示红包分数增加动画
|
|
|
|
|
+ this.showRedPacketScoreAnimation();
|
|
|
|
|
+ }
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
|
|
//初始化网格
|
|
//初始化网格
|
|
@@ -1265,8 +1288,8 @@ export class EliminateViewComp extends CCComp {
|
|
|
// 显示红包分数增加动画
|
|
// 显示红包分数增加动画
|
|
|
private showRedPacketScoreAnimation() {
|
|
private showRedPacketScoreAnimation() {
|
|
|
if (!this.tweenRedNode) return;
|
|
if (!this.tweenRedNode) return;
|
|
|
|
|
+ //如果有值就是要那个,没有就是取随机
|
|
|
|
|
|
|
|
- // 生成随机小数(小于1,保留2位小数)
|
|
|
|
|
const randomValue = Math.random() * 0.99;
|
|
const randomValue = Math.random() * 0.99;
|
|
|
const formattedValue = randomValue.toFixed(2);
|
|
const formattedValue = randomValue.toFixed(2);
|
|
|
|
|
|
|
@@ -1479,6 +1502,21 @@ export class EliminateViewComp extends CCComp {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+ //更新游戏分数
|
|
|
|
|
+ updateGameScore() {
|
|
|
|
|
+ if (this.score >= this.targetScore) {
|
|
|
|
|
+ //修改游戏状态
|
|
|
|
|
+ this.gameState = GameState.GAME_OVER;
|
|
|
|
|
+ //弹出恭喜通关
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 清理网格的子节点
|
|
* 清理网格的子节点
|
|
|
*/
|
|
*/
|
|
@@ -1517,13 +1555,8 @@ export class EliminateViewComp extends CCComp {
|
|
|
|
|
|
|
|
//左边微信按钮
|
|
//左边微信按钮
|
|
|
private btn_withdraw() {
|
|
private btn_withdraw() {
|
|
|
-
|
|
|
|
|
if (DeviceUtil.isNative && DeviceUtil.isAndroid) {
|
|
if (DeviceUtil.isNative && DeviceUtil.isAndroid) {
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
} else {
|
|
} else {
|
|
|
oops.gui.open(UIID.WechatWithdraw);
|
|
oops.gui.open(UIID.WechatWithdraw);
|
|
|
}
|
|
}
|
|
@@ -1555,251 +1588,213 @@ export class EliminateViewComp extends CCComp {
|
|
|
this.initButtonState(this.autoState);
|
|
this.initButtonState(this.autoState);
|
|
|
this.gameState = GameState.PLAYING
|
|
this.gameState = GameState.PLAYING
|
|
|
if (this.autoState) {
|
|
if (this.autoState) {
|
|
|
- this.startAutoMode();
|
|
|
|
|
- } else {
|
|
|
|
|
- this.stopAutoMode();
|
|
|
|
|
|
|
+ this.executeAutoPlace();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private autoModeScheduleKey: number = 0;
|
|
|
|
|
-
|
|
|
|
|
- private startAutoMode() {
|
|
|
|
|
- this.stopAutoMode(); // 确保先停止之前的自动模式
|
|
|
|
|
- const interval = this._isDoubleSpeed ? this.autoModeInterval / this._doubleNum : this.autoModeInterval;
|
|
|
|
|
- this.schedule(this.executeAutoPlacement, interval);
|
|
|
|
|
- this.autoModeScheduleKey = 0; // 不再使用返回值
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private stopAutoMode() {
|
|
|
|
|
- this.unschedule(this.executeAutoPlacement);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 调整自动放置速度
|
|
|
|
|
- public setAutoPlacementSpeed(interval: number) {
|
|
|
|
|
- this.autoModeInterval = interval;
|
|
|
|
|
- if (this.autoState) {
|
|
|
|
|
- this.startAutoMode(); // 重新启动以更新间隔
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
// 执行自动放置
|
|
// 执行自动放置
|
|
|
- private executeAutoPlacement() {
|
|
|
|
|
- if (this.editingFlag || this.gameState !== GameState.PLAYING) return;
|
|
|
|
|
|
|
+ executeAutoPlace() {
|
|
|
|
|
+ if (!this.autoState || this.gameState !== GameState.PLAYING || this.adShowingFlag || this.editingFlag) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 查找最佳放置方案
|
|
|
|
|
- const bestPlacement = this.findBestPlacement();
|
|
|
|
|
|
|
+ const bestPlacement = this.findBestPlacement()
|
|
|
if (!bestPlacement) {
|
|
if (!bestPlacement) {
|
|
|
- this.gameOver();
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ // 所有方块都无法放置,游戏结束
|
|
|
|
|
+ this.autoState = false
|
|
|
|
|
+ this.gameOver()
|
|
|
|
|
+ return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- this.autoPlaceBrick(bestPlacement);
|
|
|
|
|
|
|
+ // 执行放置
|
|
|
|
|
+ this.placeBrickAtPosition(bestPlacement)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ //寻找最佳位置
|
|
|
|
|
+ findBestPlacement() {
|
|
|
|
|
+ const placements = []
|
|
|
|
|
+
|
|
|
|
|
+ // 对每个方块计算所有可能的放置位置和分数
|
|
|
|
|
+ for (let brickIndex = 0; brickIndex < this.bricksList.length; brickIndex++) {
|
|
|
|
|
+ const brickData = this.bricksList[brickIndex]
|
|
|
|
|
+
|
|
|
|
|
+ // 检查不同旋转状态
|
|
|
|
|
+ let gridConfigs = [brickData.gridConfig]
|
|
|
|
|
+ let degrees = [brickData.deg]
|
|
|
|
|
+
|
|
|
|
|
+ // 如果可旋转,计算所有旋转状态
|
|
|
|
|
+ if (brickData.rotateFlag) {
|
|
|
|
|
+ for (let i = 1; i <= 3; i++) {
|
|
|
|
|
+ const next = this.nextGridRotate(
|
|
|
|
|
+ i === 1 ? brickData.gridConfig : gridConfigs[i - 1],
|
|
|
|
|
+ i === 1 ? brickData.deg : degrees[i - 1]
|
|
|
|
|
+ )
|
|
|
|
|
+ gridConfigs.push(next.gridConfig)
|
|
|
|
|
+ degrees.push(next.deg)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 遍历所有网格位置
|
|
|
|
|
+ for (let rowIndex = 0; rowIndex < this.rows; rowIndex++) {
|
|
|
|
|
+ for (let columnIndex = 0; columnIndex < this.cols; columnIndex++) {
|
|
|
|
|
+ // 对每个旋转状态检查
|
|
|
|
|
+ for (let rotateIndex = 0; rotateIndex < gridConfigs.length; rotateIndex++) {
|
|
|
|
|
+ const currentGridConfig = gridConfigs[rotateIndex]
|
|
|
|
|
+ const currentDeg = degrees[rotateIndex]
|
|
|
|
|
|
|
|
- // 查找最佳放置方案
|
|
|
|
|
- private findBestPlacement() {
|
|
|
|
|
- // 最佳放置方案
|
|
|
|
|
- let bestPlacement: {
|
|
|
|
|
- brickIndex: number,
|
|
|
|
|
- row: number,
|
|
|
|
|
- column: number,
|
|
|
|
|
- rotateCount: number,
|
|
|
|
|
- score: number
|
|
|
|
|
- } | null = null;
|
|
|
|
|
-
|
|
|
|
|
- // 遍历所有方块
|
|
|
|
|
- for (let brickI = 0; brickI < this.bricksList.length; brickI++) {
|
|
|
|
|
- const brickData = this.bricksList[brickI];
|
|
|
|
|
-
|
|
|
|
|
- // 尝试所有可能的旋转状态
|
|
|
|
|
- let currentGridConfig = [...brickData.gridConfig];
|
|
|
|
|
- let currentDeg = brickData.deg;
|
|
|
|
|
-
|
|
|
|
|
- for (let rotateCount = 0; rotateCount < 4; rotateCount++) {
|
|
|
|
|
- // 遍历所有网格位置
|
|
|
|
|
- for (let rowIndex = 0; rowIndex < this.rows; rowIndex++) {
|
|
|
|
|
- for (let columnIndex = 0; columnIndex < this.cols; columnIndex++) {
|
|
|
|
|
// 检查是否可以放置
|
|
// 检查是否可以放置
|
|
|
if (this.moveIf(rowIndex, columnIndex, currentGridConfig)) {
|
|
if (this.moveIf(rowIndex, columnIndex, currentGridConfig)) {
|
|
|
- // 复制网格状态并模拟放置
|
|
|
|
|
- const gridListCopy = this.copyGridList();
|
|
|
|
|
- currentGridConfig.forEach((configData) => {
|
|
|
|
|
- gridListCopy[configData.row + rowIndex][configData.column + columnIndex].status = CellState.FILLED;
|
|
|
|
|
- gridListCopy[configData.row + rowIndex][configData.column + columnIndex].type = brickData.type;
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // 计算放置后的分数
|
|
|
|
|
- const eliminateResult = this.gridEliminateCheck(gridListCopy);
|
|
|
|
|
- const eliminatedCount = eliminateResult.gridEliminateList.length;
|
|
|
|
|
- const eliminateRowNum = eliminateResult.eliminateRowNum;
|
|
|
|
|
- const eliminateColumnNum = eliminateResult.eliminateColumnNum;
|
|
|
|
|
-
|
|
|
|
|
- let score = 0;
|
|
|
|
|
- // 有消除,计算消除分数
|
|
|
|
|
- if (eliminatedCount > 0) {
|
|
|
|
|
- // 行消除基础分
|
|
|
|
|
- for (let i = 1; i <= eliminateRowNum; i++) {
|
|
|
|
|
- score += this.eliminateBaseScore; // 每行基础分
|
|
|
|
|
- score += (this.cols - 1) * this.extraGridScore; // 额外格子分
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 复制网格并模拟放置
|
|
|
|
|
+ const gridList = this.copyGridList()
|
|
|
|
|
+ currentGridConfig.forEach((gridConfigData) => {
|
|
|
|
|
+ const r = gridConfigData.row + rowIndex
|
|
|
|
|
+ const c = gridConfigData.column + columnIndex
|
|
|
|
|
+ gridList[r][c].status = CellState.FILLED
|
|
|
|
|
+ // gridList[r][c].gridColorKey = brickData.gridColorKey
|
|
|
|
|
+ gridList[r][c].type = brickData.type;
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- // 列消除基础分
|
|
|
|
|
- for (let i = 1; i <= eliminateColumnNum; i++) {
|
|
|
|
|
- score += this.eliminateBaseScore; // 每列基础分
|
|
|
|
|
- score += (this.rows - 1) * this.extraGridScore; // 额外格子分
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 检查是否可以消除,计算分数
|
|
|
|
|
+ const elimination = this.gridEliminateCheck(gridList)
|
|
|
|
|
+ let score = 0
|
|
|
|
|
|
|
|
- // 如果没有消除,给予放置的块数作为基础分
|
|
|
|
|
- if (score === 0) {
|
|
|
|
|
- score = currentGridConfig.length * this.placementBaseScore;
|
|
|
|
|
|
|
+ if (elimination.gridEliminateList.length > 0) {
|
|
|
|
|
+ // 计算消除得分
|
|
|
|
|
+ for (let i = 1; i <= elimination.eliminateRowNum; i++) {
|
|
|
|
|
+ score += this.cols * i
|
|
|
|
|
+ }
|
|
|
|
|
+ for (let i = 1; i <= elimination.eliminateColumnNum; i++) {
|
|
|
|
|
+ score += this.rows * i
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 更新最佳方案
|
|
|
|
|
- if (!bestPlacement || score > bestPlacement.score) {
|
|
|
|
|
- bestPlacement = {
|
|
|
|
|
- brickIndex: brickI,
|
|
|
|
|
- row: rowIndex,
|
|
|
|
|
- column: columnIndex,
|
|
|
|
|
- rotateCount: rotateCount,
|
|
|
|
|
- score: score
|
|
|
|
|
- };
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 记录此放置选项
|
|
|
|
|
+ placements.push({
|
|
|
|
|
+ brickIndex,
|
|
|
|
|
+ brickData,
|
|
|
|
|
+ rowIndex,
|
|
|
|
|
+ columnIndex,
|
|
|
|
|
+ gridConfig: currentGridConfig,
|
|
|
|
|
+ deg: currentDeg,
|
|
|
|
|
+ score,
|
|
|
|
|
+ canEliminate: elimination.gridEliminateList.length > 0
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- // 旋转方块到下一个状态
|
|
|
|
|
- if (rotateCount < 3 && brickData.rotateFlag) {
|
|
|
|
|
- const next = this.nextGridRotate(currentGridConfig, currentDeg);
|
|
|
|
|
- currentGridConfig = next.gridConfig;
|
|
|
|
|
- currentDeg = next.deg;
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return bestPlacement;
|
|
|
|
|
|
|
+ // 按优先级排序:最高分 > 有分数 > 没有分数但可放置
|
|
|
|
|
+ placements.sort((a, b) => {
|
|
|
|
|
+ // 首先按分数排序
|
|
|
|
|
+ if (a.score !== b.score) {
|
|
|
|
|
+ return b.score - a.score
|
|
|
|
|
+ }
|
|
|
|
|
+ // 其次按是否可消除排序
|
|
|
|
|
+ if (a.canEliminate !== b.canEliminate) {
|
|
|
|
|
+ return a.canEliminate ? -1 : 1
|
|
|
|
|
+ }
|
|
|
|
|
+ // 最后按照方块优先级排序(底部的方块优先)
|
|
|
|
|
+ return a.brickIndex - b.brickIndex
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ return placements.length > 0 ? placements[0] : null
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 自动放置方块
|
|
|
|
|
- private autoPlaceBrick(placement: { brickIndex: number, row: number, column: number, rotateCount: number, score: number }) {
|
|
|
|
|
- const brickData = this.bricksList[placement.brickIndex];
|
|
|
|
|
- if (!brickData || !brickData.brickNode) return;
|
|
|
|
|
- console.log("brickData>>>>>>", brickData);
|
|
|
|
|
- // 获取方块节点
|
|
|
|
|
- const brickNode = brickData.brickNode;
|
|
|
|
|
-
|
|
|
|
|
- // 先将方块移到移动层以便显示动画
|
|
|
|
|
- const originalParent = brickNode.parent;
|
|
|
|
|
- const startPos = brickNode.getWorldPosition().clone();
|
|
|
|
|
- brickNode.setParent(this.moveNode);
|
|
|
|
|
- brickNode.setWorldPosition(startPos);
|
|
|
|
|
-
|
|
|
|
|
- // 放大方块
|
|
|
|
|
- tween(brickNode)
|
|
|
|
|
- .to(0.2, { scale: new Vec3(1, 1, 1) })
|
|
|
|
|
- .start();
|
|
|
|
|
|
|
+ // ... existing code ...
|
|
|
|
|
|
|
|
- // 从方块列表中移除该方块
|
|
|
|
|
- this.bricksList.splice(placement.brickIndex, 1);
|
|
|
|
|
-
|
|
|
|
|
- // 先应用旋转到实际的brickData中,这样放置和显示保持一致
|
|
|
|
|
- if (placement.rotateCount > 0 && brickData.rotateFlag) {
|
|
|
|
|
- let currentGridConfig = [...brickData.gridConfig];
|
|
|
|
|
- let currentDeg = brickData.deg;
|
|
|
|
|
- for (let i = 0; i < placement.rotateCount; i++) {
|
|
|
|
|
- const next = this.nextGridRotate(currentGridConfig, currentDeg);
|
|
|
|
|
- currentGridConfig = next.gridConfig;
|
|
|
|
|
- currentDeg = next.deg;
|
|
|
|
|
- }
|
|
|
|
|
- // 直接更新brickData的配置
|
|
|
|
|
- brickData.gridConfig = currentGridConfig;
|
|
|
|
|
- brickData.deg = currentDeg;
|
|
|
|
|
|
|
+ placeBrickAtPosition(placement: any) {
|
|
|
|
|
+ const brickData = placement.brickData
|
|
|
|
|
+ const index = this.bricksList.findIndex(data => data === brickData)
|
|
|
|
|
+ if (index === -1) {
|
|
|
|
|
+ console.error("无法找到要放置的方块:", brickData)
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ this.editingData.brickData = this.bricksList.splice(index, 1)[0];
|
|
|
|
|
+ // 应用旋转
|
|
|
|
|
+ if (brickData.deg !== placement.deg) {
|
|
|
|
|
+ brickData.gridConfig = placement.gridConfig
|
|
|
|
|
+ brickData.deg = placement.deg
|
|
|
|
|
+ tween(brickData.brickNode).to(0.1, { angle: placement.deg }).start()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 计算目标网格的中心位置
|
|
|
|
|
- const targetGridList: GridData[] = [];
|
|
|
|
|
- let targetPos = new Vec3(0, 0, 0);
|
|
|
|
|
-
|
|
|
|
|
- // 计算目标位置,使用更新后的brickData.gridConfig
|
|
|
|
|
- brickData.gridConfig.forEach(configData => {
|
|
|
|
|
- const gridRow = configData.row + placement.row;
|
|
|
|
|
- const gridCol = configData.column + placement.column;
|
|
|
|
|
- if (gridRow >= 0 && gridRow < this.rows && gridCol >= 0 && gridCol < this.cols) {
|
|
|
|
|
- const grid = this.gridList[gridRow][gridCol];
|
|
|
|
|
- if (grid.gridNode) {
|
|
|
|
|
- targetGridList.push(grid);
|
|
|
|
|
- targetPos.add(grid.gridNode.getWorldPosition());
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ // 构建对应网格列表
|
|
|
|
|
+ this.editingData.gridList = []
|
|
|
|
|
+ placement.gridConfig.forEach((gridConfigData) => {
|
|
|
|
|
+ const r = gridConfigData.row + placement.rowIndex
|
|
|
|
|
+ const c = gridConfigData.column + placement.columnIndex
|
|
|
|
|
+ this.editingData.gridList.push(this.gridList[r][c])
|
|
|
|
|
+ })
|
|
|
|
|
|
|
|
- console.log("this.gridList", this.gridList);
|
|
|
|
|
- if (targetGridList.length > 0) {
|
|
|
|
|
- targetPos.x /= targetGridList.length;
|
|
|
|
|
- targetPos.y /= targetGridList.length;
|
|
|
|
|
- }
|
|
|
|
|
- // 创建动画序列
|
|
|
|
|
- const tweenSequence = tween(brickNode);
|
|
|
|
|
|
|
|
|
|
- // 1. 先执行旋转动画(如果需要)
|
|
|
|
|
- if (placement.rotateCount > 0 && brickData.rotateFlag) {
|
|
|
|
|
- tweenSequence.to(0.3, { angle: brickData.deg });
|
|
|
|
|
|
|
+ // 计算移动位置(中点)
|
|
|
|
|
+ let centerPos = new Vec3(0, 0, 0)
|
|
|
|
|
+ let count = 0
|
|
|
|
|
+ for (const grid of this.editingData.gridList) {
|
|
|
|
|
+ if (grid.gridNode) {
|
|
|
|
|
+ const pos = grid.gridNode.getWorldPosition()
|
|
|
|
|
+ centerPos.add(pos)
|
|
|
|
|
+ count++
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (count > 0) {
|
|
|
|
|
+ centerPos.x /= count
|
|
|
|
|
+ centerPos.y /= count
|
|
|
|
|
+ centerPos.z /= count
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 2. 再执行移动动画
|
|
|
|
|
- tweenSequence.to(0.5, { worldPosition: targetPos });
|
|
|
|
|
-
|
|
|
|
|
- // 3. 动画完成后更新网格和执行后续操作
|
|
|
|
|
- tweenSequence.call(() => {
|
|
|
|
|
- // 放置方块到网格
|
|
|
|
|
- targetGridList.forEach(grid => {
|
|
|
|
|
- grid.status = CellState.FILLED;
|
|
|
|
|
- grid.type = brickData.type;
|
|
|
|
|
- //这是对的
|
|
|
|
|
- console.log(">>>>>>>>>>>>>>>>>", grid);
|
|
|
|
|
- this.generateGrid(grid);
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ const originPos = brickData.brickNode.getWorldPosition()
|
|
|
|
|
+ brickData.brickNode.setParent(this.moveNode)
|
|
|
|
|
+ brickData.brickNode.setWorldPosition(originPos)
|
|
|
|
|
|
|
|
- // 显示得分动画
|
|
|
|
|
- this.showScoreAnimation(targetPos, targetGridList.length);
|
|
|
|
|
|
|
+ // 动画放置方块
|
|
|
|
|
+ tween(brickData.brickNode)
|
|
|
|
|
+ .to(0.2, { worldPosition: centerPos })
|
|
|
|
|
+ .call(() => {
|
|
|
|
|
+ // ✅ 更新格子状态(像手动放置那样)
|
|
|
|
|
+ this.editingData.gridList.forEach(gridData => {
|
|
|
|
|
+ gridData.status = CellState.FILLED
|
|
|
|
|
+ // gridData.gridColorKey = brickData.gridColorKey
|
|
|
|
|
+ gridData.type = brickData.type;
|
|
|
|
|
+
|
|
|
|
|
+ this.generateGrid(gridData)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // ✅ 销毁方块节点
|
|
|
|
|
+ brickData.brickNode.destroy()
|
|
|
|
|
+
|
|
|
|
|
+ // ✅ 补充新的砖块
|
|
|
|
|
+ this.addBrick(brickData.index)
|
|
|
|
|
+
|
|
|
|
|
+ // ✅ 消除检查逻辑保持和手动一致
|
|
|
|
|
+ this.scheduleOnce(() => {
|
|
|
|
|
+ this.gridEliminate().then(() => {
|
|
|
|
|
+ this.prompt(false).then((promptFlag) => {
|
|
|
|
|
+ if (!promptFlag) {
|
|
|
|
|
+ this.autoState = false
|
|
|
|
|
+ this.gameOver()
|
|
|
|
|
+ } else if (this.autoState) {
|
|
|
|
|
+ // 继续自动放置
|
|
|
|
|
+ this.scheduleOnce(() => {
|
|
|
|
|
+ this.executeAutoPlace()
|
|
|
|
|
+ }, 0.3)
|
|
|
|
|
+ }
|
|
|
|
|
+ this.editingFlag = false
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+ .start()
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 标记需要重置消除计数器
|
|
|
|
|
- this.shouldResetEliminateCount = true;
|
|
|
|
|
|
|
|
|
|
- // 销毁方块节点
|
|
|
|
|
- brickNode.destroy();
|
|
|
|
|
|
|
|
|
|
- // 添加新方块到待选区
|
|
|
|
|
- this.addBrick(brickData.index);
|
|
|
|
|
|
|
|
|
|
- // 检查消除
|
|
|
|
|
- this.scheduleOnce(() => {
|
|
|
|
|
- this.gridEliminate().then((hasElimination) => {
|
|
|
|
|
- // 如果没有消除,确保下次消除会重置计数
|
|
|
|
|
- if (!hasElimination) {
|
|
|
|
|
- this.shouldResetEliminateCount = true;
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- // 检查游戏是否结束
|
|
|
|
|
- this.prompt(false).then(canContinue => {
|
|
|
|
|
- if (!canContinue) {
|
|
|
|
|
- this.gameOver();
|
|
|
|
|
- this.stopAutoMode();
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
- });
|
|
|
|
|
- }, 0.1);
|
|
|
|
|
- });
|
|
|
|
|
|
|
|
|
|
- // 应用二倍速度
|
|
|
|
|
- // 注意:在当前引擎版本中无法直接调整tween的速度
|
|
|
|
|
- // 如需二倍速效果,应在创建tween时直接调整动画持续时间
|
|
|
|
|
|
|
|
|
|
- // 启动动画
|
|
|
|
|
- tweenSequence.start();
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
doubleSpeedOpenSuccess() {
|
|
doubleSpeedOpenSuccess() {
|