| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- /*
- * @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;
- }
- }
- }
- }
|