/* * @Author: mojunshou 1637302775@qq.com * @Date: 2025-03-27 15:04:15 * @LastEditors: mojunshou 1637302775@qq.com * @LastEditTime: 2025-03-27 15:21:52 * @Description: */ import { tween, Color, Sprite, UITransform, UIOpacity, v3 } from 'cc'; import { _decorator, EventTouch, Prefab, SpriteFrame, Vec3, Node } from 'cc'; import { GameComponent } from "db://oops-framework/module/common/GameComponent"; const { ccclass, property } = _decorator; // 定义方块类型 export enum BlockColorType { RED = 0, BLUE = 1, GREEN = 2, YELLOW = 3, PURPLE = 4 } // 定义方块形状模板(每种形状的格子偏移位置) export const BLOCK_SHAPES = [ // I形状 [[0, 0], [0, 1], [0, 2]], // L形状 [[0, 0], [0, 1], [1, 1]], // 反L形状 [[0, 0], [0, 1], [-1, 1]], // T形状 [[0, 0], [-1, 0], [1, 0], [0, 1]], // 方形 [[0, 0], [1, 0], [0, 1], [1, 1]], // Z形状 [[0, 0], [1, 0], [0, 1], [-1, 1]], // S形状 [[0, 0], [-1, 0], [0, 1], [1, 1]] ]; /** 显示对象控制 */ @ccclass('BlockItemView') export class BlockItemView extends GameComponent { @property([SpriteFrame]) blockSprites: SpriteFrame[] = []; @property(Prefab) cellPrefab: Prefab = null!; // 方块当前类型 private blockType: BlockColorType = BlockColorType.RED; // 方块形状索引 private shapeIndex: number = 0; // 方块图标索引 private iconIndex: number = 0; // 方块单元格尺寸 private cellSize: number = 82; // 方块单元格节点数组 private cells: Node[] = []; // 方块当前形状表示(格子坐标偏移) private currentShape: number[][] = []; // 是否可以旋转 private isRotatable: boolean = false; // 是否可以拖拽 private isDraggable: boolean = true; // 是否正在拖拽 private isDragging: boolean = false; // 原始位置(拖拽失败时返回) private originalPosition: Vec3 = null!; protected start() { this.originalPosition = this.node.position.clone(); this.initEventListeners(); } /** * 初始化事件监听 */ initEventListeners() { this.node.on(Node.EventType.TOUCH_START, this.onTouchStart, this); this.node.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this); this.node.on(Node.EventType.TOUCH_END, this.onTouchEnd, this); this.node.on(Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this); } /** * 触摸开始事件 */ onTouchStart(event: EventTouch) { console.log("onTouchStart"); if (!this.isDraggable) return; this.isDragging = true; this.originalPosition = this.node.position.clone(); // 通知游戏组件方块被选中 this.node.emit('block_selected', this); } /** * 触摸移动事件 */ onTouchMove(event: EventTouch) { if (!this.isDragging) return; const delta = event.getDelta(); this.node.setPosition( this.node.position.x + delta.x, this.node.position.y + delta.y, this.node.position.z ); // 通知游戏组件方块正在移动 this.node.emit('block_moving', { block: this, position: this.node.position }); } /** * 触摸结束事件 */ onTouchEnd(event: EventTouch) { if (!this.isDragging) return; this.isDragging = false; // 通知游戏组件方块放置 this.node.emit('block_placed', { block: this, position: this.node.position }); } /** * 返回原始位置 */ returnToOriginalPosition() { tween(this.node) .to(0.3, { position: this.originalPosition }) .start(); } /** * 移动到指定位置 */ moveTo(position: Vec3) { tween(this.node) .to(0.3, { position: position }) .start(); } /** * 高亮显示(可放置提示) */ highlight(isValid: boolean) { const color = isValid ? new Color(150, 255, 150, 255) : new Color(255, 150, 150, 255); for (const cell of this.cells) { const sprite = cell.getComponent(Sprite); if (sprite) { sprite.color = color; } } } /** * 取消高亮 */ resetHighlight() { for (const cell of this.cells) { const sprite = cell.getComponent(Sprite); if (sprite) { sprite.color = Color.WHITE; } } } /** * 获取当前方块形状中所有单元格的世界坐标 */ getCellWorldPositions(): Vec3[] { const positions: Vec3[] = []; for (const cell of this.cells) { const transform = this.node.getComponent(UITransform); if (transform) { positions.push(transform.convertToWorldSpaceAR(cell.position)); } } return positions; } /** * 获取当前方块类型 */ getBlockType(): BlockColorType { return this.blockType; } /** * 获取当前方块形状 */ getCurrentShape(): number[][] { return this.currentShape; } /** * 执行消除动画 */ playEliminateAnimation(callback?: Function) { // 播放消除动画 const duration = 0.3; for (const cell of this.cells) { // 确保有 UIOpacity 组件 let uiOpacity = cell.getComponent(UIOpacity); if (!uiOpacity) { uiOpacity = cell.addComponent(UIOpacity); } tween(cell) .to(duration, { scale: v3(0, 0, 1) }) .start(); tween(uiOpacity) .to(duration, { opacity: 0 }) .start(); } // 动画结束后执行回调 this.scheduleOnce(() => { if (callback) callback(); }, duration); } /** * 设置是否可拖拽 */ setDraggable(draggable: boolean) { this.isDraggable = draggable; } /** * 父节点点击事件 */ onParentNodeClicked(event: EventTouch) { if (!this.isDraggable) return; this.isDragging = true; this.originalPosition = this.node.position.clone(); // 通知游戏组件方块被选中 this.node.emit('block_selected', this); } /** * 设置this.cellPrefab下边icon 的样式 * */ setBlockSpriteFrame(spriteFrame: SpriteFrame) { for (const cell of this.cells) { const sprite = cell.getChildByName("icon")?.getComponent(Sprite); if (sprite) { sprite.spriteFrame = spriteFrame; } } } }