|
@@ -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-03-28 11:47:41
|
|
|
|
|
|
|
+ * @LastEditTime: 2025-03-28 17:23:57
|
|
|
* @Description: 消除游戏主场景
|
|
* @Description: 消除游戏主场景
|
|
|
*/
|
|
*/
|
|
|
import { _decorator, Color, EventTouch, instantiate, JsonAsset, Label, Node, Prefab, randomRangeInt, Sprite, Toggle, tween, UITransform, Vec2, Vec3, Widget } from "cc";
|
|
import { _decorator, Color, EventTouch, instantiate, JsonAsset, Label, Node, Prefab, randomRangeInt, Sprite, Toggle, tween, UITransform, Vec2, Vec3, Widget } from "cc";
|
|
@@ -119,6 +119,11 @@ export class EliminateViewComp extends CCComp {
|
|
|
|
|
|
|
|
@property({ type: Prefab, displayName: "旋转预制体" })
|
|
@property({ type: Prefab, displayName: "旋转预制体" })
|
|
|
private rotatePrefab: Node = null!;
|
|
private rotatePrefab: Node = null!;
|
|
|
|
|
+ @property({ type: Label, displayName: "累计消除次数" })
|
|
|
|
|
+ private lab_total: Label = null!;
|
|
|
|
|
+ @property({ type: Label, displayName: "每次放置添加的分数" })
|
|
|
|
|
+ private lab_addScore: Label = null!;
|
|
|
|
|
+
|
|
|
|
|
|
|
|
private lab_speed: Label = null!;
|
|
private lab_speed: Label = null!;
|
|
|
private winthdrawNode: Node = null!;
|
|
private winthdrawNode: Node = null!;
|
|
@@ -140,11 +145,13 @@ export class EliminateViewComp extends CCComp {
|
|
|
private money: number = 0; //左边金钱
|
|
private money: number = 0; //左边金钱
|
|
|
private cash: number = 0; //右边红包钱数
|
|
private cash: number = 0; //右边红包钱数
|
|
|
|
|
|
|
|
|
|
+ private totalNum: number = 0; //累计消除次数,断了就是又从0开始
|
|
|
|
|
+
|
|
|
//网格列表
|
|
//网格列表
|
|
|
// gridsNode: Node | null = null; //中间网格区域
|
|
// gridsNode: Node | null = null; //中间网格区域
|
|
|
// brickNode: Node | null = null; //底部三个item块区域
|
|
// brickNode: Node | null = null; //底部三个item块区域
|
|
|
// moveNode: Node | null = null; //移动层Node
|
|
// moveNode: Node | null = null; //移动层Node
|
|
|
- // rotateNode: Node | null = null; //旋转Node
|
|
|
|
|
|
|
+ // rotateNode: Node | null = null; //旋转Node吧
|
|
|
|
|
|
|
|
//没使用颜色
|
|
//没使用颜色
|
|
|
notUseColor = new Color(255, 255, 255, 255)
|
|
notUseColor = new Color(255, 255, 255, 255)
|
|
@@ -154,7 +161,7 @@ export class EliminateViewComp extends CCComp {
|
|
|
unavailableColor = new Color(255, 0, 0, 100)
|
|
unavailableColor = new Color(255, 0, 0, 100)
|
|
|
//旋转容错
|
|
//旋转容错
|
|
|
rotateFaultTolerant = 10;
|
|
rotateFaultTolerant = 10;
|
|
|
- private _isAutoFunc: (() => void) | null = null
|
|
|
|
|
|
|
+ private _isAutoFunc: (() => void) | null = null;
|
|
|
|
|
|
|
|
isAutoMode: boolean = false;
|
|
isAutoMode: boolean = false;
|
|
|
autoModeInterval: number = 1 // 自动模式的间隔时间(秒)
|
|
autoModeInterval: number = 1 // 自动模式的间隔时间(秒)
|
|
@@ -185,6 +192,9 @@ export class EliminateViewComp extends CCComp {
|
|
|
// 方块数据保存数组,生成后就保存起来
|
|
// 方块数据保存数组,生成后就保存起来
|
|
|
private brickList: BrickData[] = [];
|
|
private brickList: BrickData[] = [];
|
|
|
|
|
|
|
|
|
|
+ // 添加新的属性来跟踪是否需要重置消除计数
|
|
|
|
|
+ private shouldResetEliminateCount: boolean = true;
|
|
|
|
|
+ private consecutiveEliminations: boolean = false;
|
|
|
|
|
|
|
|
/** 视图层逻辑代码分离演示 */
|
|
/** 视图层逻辑代码分离演示 */
|
|
|
async start() {
|
|
async start() {
|
|
@@ -258,6 +268,9 @@ export class EliminateViewComp extends CCComp {
|
|
|
this.score = 0;
|
|
this.score = 0;
|
|
|
this.money = 0;
|
|
this.money = 0;
|
|
|
this.cash = 0;
|
|
this.cash = 0;
|
|
|
|
|
+ this.totalNum = 0;
|
|
|
|
|
+ this.shouldResetEliminateCount = true;
|
|
|
|
|
+ this.consecutiveEliminations = false;
|
|
|
this.lab_score.string = this.score.toString();
|
|
this.lab_score.string = this.score.toString();
|
|
|
this.amountLb.string = this.money.toString();
|
|
this.amountLb.string = this.money.toString();
|
|
|
this.awardLb.string = this.cash.toString();
|
|
this.awardLb.string = this.cash.toString();
|
|
@@ -588,235 +601,271 @@ export class EliminateViewComp extends CCComp {
|
|
|
// 确保节点可交互
|
|
// 确保节点可交互
|
|
|
brickNode.active = true;
|
|
brickNode.active = true;
|
|
|
|
|
|
|
|
- // 移除可能存在的旧事件监听器,防止重复添加
|
|
|
|
|
|
|
+ // 移除可能存在的旧事件监听器
|
|
|
brickNode.off(Node.EventType.TOUCH_START);
|
|
brickNode.off(Node.EventType.TOUCH_START);
|
|
|
brickNode.off(Node.EventType.TOUCH_MOVE);
|
|
brickNode.off(Node.EventType.TOUCH_MOVE);
|
|
|
brickNode.off(Node.EventType.TOUCH_END);
|
|
brickNode.off(Node.EventType.TOUCH_END);
|
|
|
|
|
+ brickNode.off(Node.EventType.TOUCH_CANCEL);
|
|
|
|
|
|
|
|
- // 添加调试日志
|
|
|
|
|
- console.log(`为节点 ${brickNode.name} 添加触摸事件监听器`);
|
|
|
|
|
|
|
+ // 记录初始位置和状态
|
|
|
|
|
+ let startPos = new Vec3();
|
|
|
|
|
+ let originalParent: Node | null = null;
|
|
|
|
|
+ let isDragging = false;
|
|
|
|
|
|
|
|
- // 添加触摸开始事件
|
|
|
|
|
|
|
+ // 触摸开始事件
|
|
|
brickNode.on(Node.EventType.TOUCH_START, (event: EventTouch) => {
|
|
brickNode.on(Node.EventType.TOUCH_START, (event: EventTouch) => {
|
|
|
- console.log("触发TOUCH_START事件");
|
|
|
|
|
- // 未操作完时不能操作下一个方块
|
|
|
|
|
- if (this.editingFlag) return
|
|
|
|
|
- this.touchStartFlag = true
|
|
|
|
|
- this.editingFlag = true
|
|
|
|
|
- this.editingData.brickData = null
|
|
|
|
|
- this.editingData.gridList.length = 0
|
|
|
|
|
-
|
|
|
|
|
- // 记录开始触摸的位置,用于结束触摸时,判断位置是否是单击
|
|
|
|
|
- this.touchStartLocation.set(event.getUILocation())
|
|
|
|
|
-
|
|
|
|
|
- // 添加到移动节点里进行移动
|
|
|
|
|
- const pos = brickNode.getWorldPosition()
|
|
|
|
|
- brickNode.setParent(this.moveNode)
|
|
|
|
|
- brickNode.setWorldPosition(pos)
|
|
|
|
|
-
|
|
|
|
|
- // 添加放大动画
|
|
|
|
|
|
|
+ // 如果正在编辑其他方块,则忽略
|
|
|
|
|
+ if (this.editingFlag) return;
|
|
|
|
|
+
|
|
|
|
|
+ // 设置编辑状态
|
|
|
|
|
+ this.editingFlag = true;
|
|
|
|
|
+ isDragging = true;
|
|
|
|
|
+ this.touchStartFlag = true;
|
|
|
|
|
+
|
|
|
|
|
+ // 清空编辑中的数据
|
|
|
|
|
+ this.editingData.brickData = null;
|
|
|
|
|
+ this.editingData.gridList.length = 0;
|
|
|
|
|
+
|
|
|
|
|
+ // 记录触摸开始位置和方块原始信息
|
|
|
|
|
+ this.touchStartLocation.set(event.getUILocation());
|
|
|
|
|
+ originalParent = brickNode.parent;
|
|
|
|
|
+ startPos = brickNode.getWorldPosition().clone();
|
|
|
|
|
+
|
|
|
|
|
+ // 将方块移到移动层并放大
|
|
|
|
|
+ brickNode.setParent(this.moveNode);
|
|
|
|
|
+ brickNode.setWorldPosition(startPos);
|
|
|
tween(brickNode)
|
|
tween(brickNode)
|
|
|
.to(0.2, { scale: new Vec3(1, 1, 1) })
|
|
.to(0.2, { scale: new Vec3(1, 1, 1) })
|
|
|
- .start()
|
|
|
|
|
|
|
+ .start();
|
|
|
|
|
|
|
|
- const index = this.bricksList.findIndex(data => data === brickData)
|
|
|
|
|
|
|
+ // 从方块列表中移除该方块
|
|
|
|
|
+ const index = this.bricksList.findIndex(item => item === brickData);
|
|
|
if (index > -1) {
|
|
if (index > -1) {
|
|
|
- this.editingData.brickData = this.bricksList.splice(index, 1)[0]
|
|
|
|
|
|
|
+ this.editingData.brickData = this.bricksList.splice(index, 1)[0];
|
|
|
} else {
|
|
} else {
|
|
|
- console.error("bricksList not find brickData:", brickData)
|
|
|
|
|
|
|
+ console.error("未找到方块数据:", brickData);
|
|
|
|
|
+ this.editingData.brickData = brickData;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 清除旋转数据
|
|
// 清除旋转数据
|
|
|
if (this.rotateFlag && this.rotateBrickData !== this.editingData.brickData) {
|
|
if (this.rotateFlag && this.rotateBrickData !== this.editingData.brickData) {
|
|
|
- this.rotateFlag = false
|
|
|
|
|
- this.rotateBrickData = null
|
|
|
|
|
|
|
+ this.rotateFlag = false;
|
|
|
|
|
+ this.rotateBrickData = null;
|
|
|
if (this.rotateNode) {
|
|
if (this.rotateNode) {
|
|
|
- this.rotateNode.children.forEach(node => { node.destroy() })
|
|
|
|
|
|
|
+ this.rotateNode.children.forEach(node => { node.destroy() });
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}, this);
|
|
}, this);
|
|
|
|
|
|
|
|
// 触摸移动事件
|
|
// 触摸移动事件
|
|
|
brickNode.on(Node.EventType.TOUCH_MOVE, (event: EventTouch) => {
|
|
brickNode.on(Node.EventType.TOUCH_MOVE, (event: EventTouch) => {
|
|
|
-
|
|
|
|
|
- // 防止如放回方块回弹动画时,已经触摸在另一个方块上面,从而导致异常错误
|
|
|
|
|
- if (this.editingData.brickData !== brickData) return
|
|
|
|
|
|
|
+ if (!isDragging || !this.editingData.brickData) return;
|
|
|
|
|
|
|
|
// 清除旋转数据
|
|
// 清除旋转数据
|
|
|
if (event.getUILocation().subtract(this.touchStartLocation).length() >= this.rotateFaultTolerant) {
|
|
if (event.getUILocation().subtract(this.touchStartLocation).length() >= this.rotateFaultTolerant) {
|
|
|
- this.rotateFlag = false
|
|
|
|
|
- this.rotateBrickData = null
|
|
|
|
|
|
|
+ this.rotateFlag = false;
|
|
|
|
|
+ this.rotateBrickData = null;
|
|
|
if (this.rotateNode) {
|
|
if (this.rotateNode) {
|
|
|
- this.rotateNode.children.forEach(node => { node.destroy() })
|
|
|
|
|
|
|
+ this.rotateNode.children.forEach(node => { node.destroy() });
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 格子颜色恢复
|
|
|
|
|
- this.gridColorRecovery()
|
|
|
|
|
-
|
|
|
|
|
- // 移动
|
|
|
|
|
- brickNode.setWorldPosition(brickNode.getWorldPosition().add(event.getUIDelta().toVec3()))
|
|
|
|
|
-
|
|
|
|
|
- // 每次移动重置数据
|
|
|
|
|
- this.editingData.gridList.length = 0
|
|
|
|
|
-
|
|
|
|
|
- // 实时获取方块位置判断在哪个格子上
|
|
|
|
|
- const tempGridList: GridData[] = []
|
|
|
|
|
- brickNode.children.forEach((brickGridNode) => {
|
|
|
|
|
- const brickGridPos = brickGridNode.getWorldPosition()
|
|
|
|
|
- let gridData: GridData | null = null
|
|
|
|
|
- for (let rowIndex = 0; rowIndex < this.rows && gridData === null; rowIndex++) {
|
|
|
|
|
- for (let columnIndex = 0; columnIndex < this.cols && gridData === null; columnIndex++) {
|
|
|
|
|
- const nowGridData = this.gridList[rowIndex][columnIndex];
|
|
|
|
|
- if (nowGridData && nowGridData.gridNode) {
|
|
|
|
|
- const gridPos = nowGridData.gridNode.getWorldPosition()
|
|
|
|
|
- if (Vec3.distance(gridPos, brickGridPos) <= (this.itemSize / 2)) {
|
|
|
|
|
- gridData = nowGridData
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 恢复所有网格颜色
|
|
|
|
|
+ this.gridColorRecovery();
|
|
|
|
|
+
|
|
|
|
|
+ // 移动方块
|
|
|
|
|
+ brickNode.setWorldPosition(brickNode.getWorldPosition().add(event.getUIDelta().toVec3()));
|
|
|
|
|
+
|
|
|
|
|
+ // 重置编辑中的网格数据
|
|
|
|
|
+ this.editingData.gridList.length = 0;
|
|
|
|
|
+
|
|
|
|
|
+ // 检查方块每个子网格是否与游戏网格重叠
|
|
|
|
|
+ const tempGridList: GridData[] = [];
|
|
|
|
|
+ let allEmptyGrids: boolean = true; // 标记是否所有网格都为空
|
|
|
|
|
+
|
|
|
|
|
+ brickNode.children.forEach((childNode) => {
|
|
|
|
|
+ const childWorldPos = childNode.getWorldPosition();
|
|
|
|
|
+
|
|
|
|
|
+ // 查找与子网格重叠的游戏网格
|
|
|
|
|
+ let matchedGrid: GridData | null = null;
|
|
|
|
|
+ for (let row = 0; row < this.rows && !matchedGrid; row++) {
|
|
|
|
|
+ for (let col = 0; col < this.cols && !matchedGrid; col++) {
|
|
|
|
|
+ const grid = this.gridList[row][col];
|
|
|
|
|
+ if (!grid || !grid.gridNode) continue;
|
|
|
|
|
+
|
|
|
|
|
+ const gridPos = grid.gridNode.getWorldPosition();
|
|
|
|
|
+ if (Vec3.distance(gridPos, childWorldPos) <= (this.itemSize / 2)) {
|
|
|
|
|
+ matchedGrid = grid;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- if (gridData === null) {
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if (matchedGrid) {
|
|
|
|
|
+ tempGridList.push(matchedGrid);
|
|
|
|
|
+ // 检查是否有非空网格
|
|
|
|
|
+ if (matchedGrid.status !== CellState.EMPTY) {
|
|
|
|
|
+ allEmptyGrids = false;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- tempGridList.push(gridData)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
- // 检查整体情况
|
|
|
|
|
- let checkFlag = false
|
|
|
|
|
- if (
|
|
|
|
|
- tempGridList.length === brickData.gridConfig.length &&
|
|
|
|
|
- tempGridList.filter(d => d.status === CellState.EMPTY).length === brickData.gridConfig.length
|
|
|
|
|
- ) {
|
|
|
|
|
- checkFlag = true
|
|
|
|
|
- tempGridList.forEach((gridData) => {
|
|
|
|
|
- this.editingData.gridList.push(gridData)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ // 检查是否所有子网格都有对应的游戏网格,且都是空的
|
|
|
|
|
+ let canPlace = tempGridList.length === brickData.gridConfig.length && allEmptyGrids;
|
|
|
|
|
+
|
|
|
|
|
+ // 更新编辑中的网格列表
|
|
|
|
|
+ if (canPlace) {
|
|
|
|
|
+ this.editingData.gridList = [...tempGridList];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 格子给用户提示
|
|
|
|
|
- tempGridList.forEach((gridData) => {
|
|
|
|
|
- if (gridData.status !== CellState.EMPTY) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if (gridData.gridNode) {
|
|
|
|
|
- const children = gridData.gridNode.children[0];
|
|
|
|
|
- if (children) {
|
|
|
|
|
- children.getComponent(Sprite)!.color = checkFlag ? this.usableColor : this.unavailableColor
|
|
|
|
|
|
|
+ // 更新网格颜色提示 - 只改变空网格的颜色
|
|
|
|
|
+ tempGridList.forEach(grid => {
|
|
|
|
|
+ // 只处理空网格
|
|
|
|
|
+ if (grid.status === CellState.EMPTY) {
|
|
|
|
|
+ if (grid.gridNode && grid.gridNode.children[0]) {
|
|
|
|
|
+ const sprite = grid.gridNode.children[0].getComponent(Sprite);
|
|
|
|
|
+ if (sprite) {
|
|
|
|
|
+ sprite.color = canPlace ? this.usableColor : this.unavailableColor;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
+ // 用于后续恢复颜色
|
|
|
|
|
+ this.gridColorList.push(grid);
|
|
|
}
|
|
}
|
|
|
- // 用于恢复格子
|
|
|
|
|
- this.gridColorList.push(gridData)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ });
|
|
|
}, this);
|
|
}, this);
|
|
|
|
|
|
|
|
- // 触摸结束事件
|
|
|
|
|
- brickNode.on(Node.EventType.TOUCH_END, (event: EventTouch) => {
|
|
|
|
|
- console.log("触发TOUCH_END事件", this.touchStartFlag);
|
|
|
|
|
|
|
+ // 触摸结束或取消事件
|
|
|
|
|
+ const touchEndHandler = (event: EventTouch) => {
|
|
|
|
|
+ if (!isDragging) return;
|
|
|
|
|
+ isDragging = false;
|
|
|
|
|
+ this.touchStartFlag = false;
|
|
|
|
|
|
|
|
- // 防止事件冒泡
|
|
|
|
|
- event.propagationStopped = true;
|
|
|
|
|
|
|
+ // 恢复网格颜色
|
|
|
|
|
+ this.gridColorRecovery();
|
|
|
|
|
|
|
|
- // 当连击很快时,会出现1次start,2次end情况,为了避免所以通过标志位表示是一个连贯操作
|
|
|
|
|
- if (!this.touchStartFlag) return
|
|
|
|
|
- this.touchStartFlag = false
|
|
|
|
|
|
|
+ // 防止如放回方块回弹动画时,已经触摸在另一个方块上面
|
|
|
|
|
+ if (this.editingData.brickData !== brickData) return;
|
|
|
|
|
+
|
|
|
|
|
+ // 检查是否可以放置
|
|
|
|
|
+ if (this.editingData.brickData && this.editingData.gridList.length > 0) {
|
|
|
|
|
+ // 计算放置的格子数量
|
|
|
|
|
+ const placedGridCount = this.editingData.gridList.length;
|
|
|
|
|
+
|
|
|
|
|
+ // 获取中心位置用于显示分数
|
|
|
|
|
+ let centerPos = new Vec3(0, 0, 0);
|
|
|
|
|
+ if (this.editingData.gridList.length > 0 && this.editingData.gridList[0].gridNode) {
|
|
|
|
|
+ centerPos = this.editingData.gridList[0].gridNode.getWorldPosition().clone();
|
|
|
|
|
+ if (this.editingData.gridList.length > 1) {
|
|
|
|
|
+ // 计算所有格子的平均位置作为中心点
|
|
|
|
|
+ for (let i = 1; i < this.editingData.gridList.length; i++) {
|
|
|
|
|
+ const gridNode = this.editingData.gridList[i].gridNode;
|
|
|
|
|
+ if (gridNode) {
|
|
|
|
|
+ centerPos.add(gridNode.getWorldPosition());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ const validGridCount = this.editingData.gridList.filter(grid => grid.gridNode).length;
|
|
|
|
|
+ centerPos.x /= validGridCount;
|
|
|
|
|
+ centerPos.y /= validGridCount;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 放置方块到网格
|
|
|
|
|
+ this.editingData.gridList.forEach(grid => {
|
|
|
|
|
+ grid.status = CellState.FILLED;
|
|
|
|
|
+ grid.gridColorKey = this.editingData.brickData!.gridColorKey;
|
|
|
|
|
+ grid.type = this.editingData.brickData!.type;
|
|
|
|
|
+ this.generateGrid(grid);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 显示放置得分动画(显示一次,包含总格子数)
|
|
|
|
|
+ this.showScoreAnimation(centerPos, placedGridCount);
|
|
|
|
|
+
|
|
|
|
|
+ // 标记需要重置消除计数器
|
|
|
|
|
+ this.shouldResetEliminateCount = true;
|
|
|
|
|
+ this.consecutiveEliminations = true;
|
|
|
|
|
+
|
|
|
|
|
+ // 销毁方块节点
|
|
|
|
|
+ brickNode.destroy();
|
|
|
|
|
+
|
|
|
|
|
+ // 添加新方块到待选区
|
|
|
|
|
+ this.addBrick(this.editingData.brickData.index);
|
|
|
|
|
|
|
|
- // 防止如放回方块回弹动画时,已经触摸在另一个方块上面,从而导致异常错误
|
|
|
|
|
- if (this.editingData.brickData !== brickData) return
|
|
|
|
|
|
|
+ // 检查消除
|
|
|
|
|
+ this.scheduleOnce(() => {
|
|
|
|
|
+ this.gridEliminate().then((hasElimination) => {
|
|
|
|
|
+ // 如果没有消除,确保下次消除会重置计数
|
|
|
|
|
+ if (!hasElimination) {
|
|
|
|
|
+ this.shouldResetEliminateCount = true;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 第二次单击,旋转
|
|
|
|
|
- if (this.rotateFlag) {
|
|
|
|
|
- const brickData = this.editingData.brickData
|
|
|
|
|
- this.brickGridRotate(brickData)
|
|
|
|
|
|
|
+ // 检查游戏是否结束
|
|
|
|
|
+ this.prompt(false).then(canContinue => {
|
|
|
|
|
+ if (!canContinue) {
|
|
|
|
|
+ this.gameOver();
|
|
|
|
|
+ }
|
|
|
|
|
+ this.editingFlag = false;
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ }, 0.1);
|
|
|
|
|
+ } else if (this.rotateFlag) {
|
|
|
|
|
+ // 旋转方块
|
|
|
|
|
+ const brickData = this.editingData.brickData;
|
|
|
|
|
+ this.brickGridRotate(brickData);
|
|
|
// 方块放回待选区
|
|
// 方块放回待选区
|
|
|
- this.bricksList.push(brickData)
|
|
|
|
|
|
|
+ this.bricksList.push(brickData);
|
|
|
if (this.brickNode && brickData.brickNode) {
|
|
if (this.brickNode && brickData.brickNode) {
|
|
|
- this.brickNode.addChild(brickData.brickNode)
|
|
|
|
|
|
|
+ this.brickNode.addChild(brickData.brickNode);
|
|
|
tween(brickData.brickNode)
|
|
tween(brickData.brickNode)
|
|
|
.to(0.2, {
|
|
.to(0.2, {
|
|
|
worldPosition: brickData.brickInitPos,
|
|
worldPosition: brickData.brickInitPos,
|
|
|
- scale: new Vec3(0.8, 0.8, 0.8)
|
|
|
|
|
|
|
+ scale: new Vec3(0.6, 0.6, 0.6)
|
|
|
})
|
|
})
|
|
|
- .start()
|
|
|
|
|
- }
|
|
|
|
|
- this.editingFlag = false
|
|
|
|
|
- }
|
|
|
|
|
- // 方块到格子
|
|
|
|
|
- else if (this.editingData.brickData && this.editingData.gridList.length > 0) {
|
|
|
|
|
- // 修改格子
|
|
|
|
|
- this.editingData.gridList.forEach((gridData) => {
|
|
|
|
|
- gridData.status = CellState.FILLED
|
|
|
|
|
- if (this.editingData.brickData) {
|
|
|
|
|
- gridData.gridColorKey = this.editingData.brickData.gridColorKey;
|
|
|
|
|
- gridData.type = this.editingData.brickData.type;
|
|
|
|
|
- }
|
|
|
|
|
- this.generateGrid(gridData)
|
|
|
|
|
- })
|
|
|
|
|
- // 销毁方块--这增加动画
|
|
|
|
|
- if (this.editingData.brickData && this.editingData.brickData.brickNode) {
|
|
|
|
|
- this.editingData.brickData.brickNode.destroy();
|
|
|
|
|
|
|
+ .start();
|
|
|
}
|
|
}
|
|
|
- // 新增方块
|
|
|
|
|
- this.addBrick(this.editingData.brickData.index);
|
|
|
|
|
- this.scheduleOnce(() => {
|
|
|
|
|
- // 格子消除
|
|
|
|
|
- this.gridEliminate().then(() => {
|
|
|
|
|
- // 检查方块是否还能消除格子
|
|
|
|
|
- this.prompt(false).then((promptFlag) => {
|
|
|
|
|
- if (!promptFlag) {
|
|
|
|
|
- this.gameOver()
|
|
|
|
|
- }
|
|
|
|
|
- this.editingFlag = false
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- // 方块回到待选区
|
|
|
|
|
- else {
|
|
|
|
|
- console.log("返回待选区域")
|
|
|
|
|
- const brickData = this.editingData.brickData
|
|
|
|
|
- this.bricksList.push(brickData)
|
|
|
|
|
- // this.audioManager.playMoveFail()
|
|
|
|
|
- // 回弹动画
|
|
|
|
|
- if (brickData.brickNode) {
|
|
|
|
|
- tween(brickData.brickNode)
|
|
|
|
|
- .to(0.15, {
|
|
|
|
|
- worldPosition: this.editingData.brickData.brickInitPos,
|
|
|
|
|
- scale: new Vec3(0.8, 0.8, 0.8)
|
|
|
|
|
|
|
+ this.editingFlag = false;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 无法放置,将方块返回原位置
|
|
|
|
|
+ const brickData = this.editingData.brickData;
|
|
|
|
|
+ if (brickData) {
|
|
|
|
|
+ this.bricksList.push(brickData);
|
|
|
|
|
+
|
|
|
|
|
+ // 添加回弹动画
|
|
|
|
|
+ tween(brickNode)
|
|
|
|
|
+ .to(0.2, {
|
|
|
|
|
+ worldPosition: brickData.brickInitPos,
|
|
|
|
|
+ scale: new Vec3(0.6, 0.6, 0.6)
|
|
|
})
|
|
})
|
|
|
.call(() => {
|
|
.call(() => {
|
|
|
- if (this.brickNode && brickData.brickNode) {
|
|
|
|
|
- this.brickNode.addChild(brickData.brickNode);
|
|
|
|
|
- brickData.brickNode.setWorldPosition(brickData.brickInitPos);
|
|
|
|
|
|
|
+ if (originalParent) {
|
|
|
|
|
+ brickNode.setParent(originalParent);
|
|
|
|
|
+ brickNode.setWorldPosition(brickData.brickInitPos);
|
|
|
}
|
|
}
|
|
|
this.editingFlag = false;
|
|
this.editingFlag = false;
|
|
|
})
|
|
})
|
|
|
.start();
|
|
.start();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.editingFlag = false;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 旋转标志位
|
|
|
|
|
- if (
|
|
|
|
|
- !this.rotateFlag &&
|
|
|
|
|
|
|
+ // 检查是否需要处理旋转(短距离移动视为点击)
|
|
|
|
|
+ if (!this.rotateFlag &&
|
|
|
|
|
+ this.editingData.brickData &&
|
|
|
this.editingData.brickData.rotateFlag &&
|
|
this.editingData.brickData.rotateFlag &&
|
|
|
- event.getUILocation().subtract(this.touchStartLocation).length() < this.rotateFaultTolerant
|
|
|
|
|
- ) {
|
|
|
|
|
- console.log("方块旋转啦")
|
|
|
|
|
- this.rotateFlag = true
|
|
|
|
|
|
|
+ event.getUILocation().subtract(this.touchStartLocation).length() < this.rotateFaultTolerant) {
|
|
|
|
|
+ this.rotateFlag = true;
|
|
|
this.rotateBrickData = this.editingData.brickData;
|
|
this.rotateBrickData = this.editingData.brickData;
|
|
|
- if (this.rotateBrickData.brickNode) {
|
|
|
|
|
- const position = this.rotateBrickData.brickNode.getWorldPosition()
|
|
|
|
|
- const rotateNode = instantiate(this.rotatePrefab)
|
|
|
|
|
- if (this.rotateNode && rotateNode) {
|
|
|
|
|
- const instantiatedRotateNode = instantiate(rotateNode);
|
|
|
|
|
- this.rotateNode.addChild(instantiatedRotateNode);
|
|
|
|
|
- instantiatedRotateNode.setWorldPosition(position)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 显示旋转提示
|
|
|
|
|
+ if (this.rotatePrefab && this.rotateNode && brickNode) {
|
|
|
|
|
+ const rotateIndicator = instantiate(this.rotatePrefab);
|
|
|
|
|
+ this.rotateNode.addChild(rotateIndicator);
|
|
|
|
|
+ rotateIndicator.setWorldPosition(brickNode.getWorldPosition());
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- // 格子颜色恢复
|
|
|
|
|
- this.gridColorRecovery();
|
|
|
|
|
- }, this);
|
|
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ brickNode.on(Node.EventType.TOUCH_END, touchEndHandler, this);
|
|
|
|
|
+ brickNode.on(Node.EventType.TOUCH_CANCEL, touchEndHandler, this);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//格子颜色恢复
|
|
//格子颜色恢复
|
|
@@ -858,17 +907,132 @@ export class EliminateViewComp extends CCComp {
|
|
|
return { gridConfig: newGridConfig, deg: newDeg }
|
|
return { gridConfig: newGridConfig, deg: newDeg }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 消除,这里增加飞的动画
|
|
|
|
|
|
|
+ // 显示分数增加动画
|
|
|
|
|
+ showScoreAnimation(position: Vec3, score: number) {
|
|
|
|
|
+ if (!this.lab_addScore) return;
|
|
|
|
|
+
|
|
|
|
|
+ // 复制得分Label
|
|
|
|
|
+ const scoreLabel = instantiate(this.lab_addScore.node);
|
|
|
|
|
+ scoreLabel.active = true;
|
|
|
|
|
+
|
|
|
|
|
+ // 设置文本和位置
|
|
|
|
|
+ const label = scoreLabel.getComponent(Label);
|
|
|
|
|
+ if (label) {
|
|
|
|
|
+ label.string = `+${score}`;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 添加到场景中
|
|
|
|
|
+ this.node.addChild(scoreLabel);
|
|
|
|
|
+ scoreLabel.setWorldPosition(position);
|
|
|
|
|
+
|
|
|
|
|
+ // 创建动画效果
|
|
|
|
|
+ tween(scoreLabel)
|
|
|
|
|
+ .to(0.5, {
|
|
|
|
|
+ position: new Vec3(scoreLabel.position.x, scoreLabel.position.y + 50, 0),
|
|
|
|
|
+ scale: new Vec3(1.2, 1.2, 1.2)
|
|
|
|
|
+ })
|
|
|
|
|
+ .to(0.3, { opacity: 0 })
|
|
|
|
|
+ .call(() => {
|
|
|
|
|
+ scoreLabel.destroy();
|
|
|
|
|
+ })
|
|
|
|
|
+ .start();
|
|
|
|
|
+
|
|
|
|
|
+ // 更新总分
|
|
|
|
|
+ this.score += score;
|
|
|
|
|
+ this.lab_score.string = this.score.toString();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 显示消除次数动画
|
|
|
|
|
+ showEliminateCountAnimation(yPosition: number) {
|
|
|
|
|
+ if (!this.lab_total) return;
|
|
|
|
|
+
|
|
|
|
|
+ // 如果需要重置计数器,先将计数归零
|
|
|
|
|
+ if (this.shouldResetEliminateCount) {
|
|
|
|
|
+ this.totalNum = 0;
|
|
|
|
|
+ this.shouldResetEliminateCount = false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 增加累计消除次数
|
|
|
|
|
+ this.totalNum++;
|
|
|
|
|
+
|
|
|
|
|
+ // 复制总次数Label
|
|
|
|
|
+ const totalLabel = instantiate(this.lab_total.node);
|
|
|
|
|
+ totalLabel.active = true;
|
|
|
|
|
+
|
|
|
|
|
+ // 设置文本
|
|
|
|
|
+ const label = totalLabel.getComponent(Label);
|
|
|
|
|
+ if (label) {
|
|
|
|
|
+ label.string = `Combo${this.totalNum}`;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 添加到场景中
|
|
|
|
|
+ this.node.addChild(totalLabel);
|
|
|
|
|
+
|
|
|
|
|
+ // 计算网格区域的X轴中心位置,Y轴使用传入的消除行位置
|
|
|
|
|
+ const centerPos = new Vec3();
|
|
|
|
|
+ if (this.gridNode) {
|
|
|
|
|
+ // 获取网格区域的X轴中心
|
|
|
|
|
+ const worldPos = this.gridNode.getWorldPosition();
|
|
|
|
|
+ centerPos.set(worldPos.x, yPosition, worldPos.z);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ totalLabel.setWorldPosition(centerPos);
|
|
|
|
|
+
|
|
|
|
|
+ // 创建动画效果
|
|
|
|
|
+ tween(totalLabel)
|
|
|
|
|
+ .to(0.3, {
|
|
|
|
|
+ scale: new Vec3(1.5, 1.5, 1.5),
|
|
|
|
|
+ opacity: 255
|
|
|
|
|
+ })
|
|
|
|
|
+ .delay(0.5) // 停留更长时间
|
|
|
|
|
+ .to(0.4, {
|
|
|
|
|
+ scale: new Vec3(1.2, 1.2, 1.2),
|
|
|
|
|
+ position: new Vec3(totalLabel.position.x, totalLabel.position.y + 50, 0),
|
|
|
|
|
+ opacity: 0
|
|
|
|
|
+ })
|
|
|
|
|
+ .call(() => {
|
|
|
|
|
+ totalLabel.destroy();
|
|
|
|
|
+ })
|
|
|
|
|
+ .start();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 修改 gridEliminate 方法来显示消除次数
|
|
|
gridEliminate() {
|
|
gridEliminate() {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
|
|
|
|
+ return new Promise<boolean>((resolve, reject) => {
|
|
|
const d = this.gridEliminateCheck(this.gridList)
|
|
const d = this.gridEliminateCheck(this.gridList)
|
|
|
const gridEliminateList = d.gridEliminateList
|
|
const gridEliminateList = d.gridEliminateList
|
|
|
const eliminateRowNum = d.eliminateRowNum
|
|
const eliminateRowNum = d.eliminateRowNum
|
|
|
const eliminateColumnNum = d.eliminateColumnNum
|
|
const eliminateColumnNum = d.eliminateColumnNum
|
|
|
|
|
|
|
|
if (gridEliminateList.length < 1) {
|
|
if (gridEliminateList.length < 1) {
|
|
|
- resolve(false)
|
|
|
|
|
- return
|
|
|
|
|
|
|
+ // 没有发生消除
|
|
|
|
|
+ this.shouldResetEliminateCount = true; // 下一次消除需要重置计数
|
|
|
|
|
+ this.consecutiveEliminations = false; // 不是连续消除
|
|
|
|
|
+ resolve(false);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果有消除,计算消除行的平均Y轴位置
|
|
|
|
|
+ if (gridEliminateList.length > 0) {
|
|
|
|
|
+ // 计算所有被消除格子的平均Y轴位置
|
|
|
|
|
+ let totalY = 0;
|
|
|
|
|
+ let validGrids = 0;
|
|
|
|
|
+
|
|
|
|
|
+ for (const grid of gridEliminateList) {
|
|
|
|
|
+ if (grid.gridNode) {
|
|
|
|
|
+ totalY += grid.gridNode.getWorldPosition().y;
|
|
|
|
|
+ validGrids++;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 计算平均Y位置
|
|
|
|
|
+ const avgY = validGrids > 0 ? totalY / validGrids : 0;
|
|
|
|
|
+
|
|
|
|
|
+ // 标记为连续消除
|
|
|
|
|
+ this.consecutiveEliminations = true;
|
|
|
|
|
+
|
|
|
|
|
+ // 显示消除次数动画,传入Y轴位置
|
|
|
|
|
+ this.showEliminateCountAnimation(avgY);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
gridEliminateList.forEach((gridData) => {
|
|
gridEliminateList.forEach((gridData) => {
|
|
@@ -923,7 +1087,16 @@ export class EliminateViewComp extends CCComp {
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 告诉调用者有消除发生
|
|
|
resolve(true)
|
|
resolve(true)
|
|
|
|
|
+
|
|
|
|
|
+ // 检查是否需要继续消除
|
|
|
|
|
+ this.scheduleOnce(() => {
|
|
|
|
|
+ // 递归调用,检查并处理连锁消除
|
|
|
|
|
+ this.gridEliminate().then(() => {
|
|
|
|
|
+ // 连锁消除结束,不做额外处理
|
|
|
|
|
+ });
|
|
|
|
|
+ }, 0.2);
|
|
|
}, 0.2)
|
|
}, 0.2)
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
@@ -1026,6 +1199,8 @@ export class EliminateViewComp extends CCComp {
|
|
|
.start();
|
|
.start();
|
|
|
})
|
|
})
|
|
|
.start();
|
|
.start();
|
|
|
|
|
+
|
|
|
|
|
+ //需要有个金币飘的icon和文字动画,在两边,然后最后展示最新的数字
|
|
|
}, i * 0.1);
|
|
}, i * 0.1);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|