import { _decorator, BoxCollider, Camera, Component, director, EventTouch, find, Game, geometry, Layers, Layout, Node, PhysicsSystem, Quat, RigidBody, Size, tween, UITransform, v3, Vec3 } from 'cc'; import { gui } from '../../core/ui/ui'; import { UI_Idioms } from '../ui/UI_Idioms/UI_Idioms'; import { UI_Main } from '../ui/UI_Main/UI_Main'; import { Container_Manager } from './Container_Manager'; import { Cube_Infor, Cube_State } from './Cube_Infor'; import { Hall } from '../hall/Hall'; import { UI_LatticeFull } from '../ui/UI_LatticeFull/UI_LatticeFull'; import { UI_Lock } from '../ui/UI_Lock/UI_Lock'; import { Layout_Main } from '../ui/UI_Main/Layout_Main'; const { ccclass, property } = _decorator; @ccclass('GameCtl') export class GameCtl extends Component { static instance: GameCtl = null; @property(Camera) camera: Camera = null; @property([Node]) Ani: Node[] = []; Container: Container_Manager; onLoad() { GameCtl.instance = this; 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.Container = find('Container').getComponent(Container_Manager); } update(deltaTime: number) { } onTouchStart(event: EventTouch) { } onTouchMove(event: EventTouch) { } onTouchEnd(event: EventTouch) { if (this.Container.canTouch) { this.shootRay(event); } } //发射射线检测判断物体是否可消除 shootRay(event: EventTouch) { if (!this.camera) return; let ray = new geometry.Ray(); this.camera.screenPointToRay(event.getLocationX(), event.getLocationY(), ray); if (PhysicsSystem.instance.raycastClosest(ray)) { const raycastClosestResult = PhysicsSystem.instance.raycastClosestResult; const collider = raycastClosestResult.collider; console.log(collider.node.name); //当前其余点击无效 if (collider.node.getComponent(Cube_Infor)?.state === Cube_State.live) { // if(gui.get(UI_Main).getLayout().Hand.active==true) // { // gui.get(UI_Main).getLayout().Hand.active=false; // } this.entryContainer(collider.node); } else if (collider.node.name == 'Lock') { //解锁槽子 this.UnLock(collider.node); } } console.log('发射了射线'); } entryContainer(node: Node) { // 判断容器剩余容量 let startIndex = -1; let targetPos = new Vec3(); let txt_length = node.getComponent(Cube_Infor).Text.length; console.log(txt_length); // 判断字长 并 判断是否还有空间可放置 switch (txt_length) { case 1: for (let i = 0; i < this.Container.unlock_Num; i++) { if (this.Container.node_isIdiom[i] === false) { startIndex = i; // 找到连续的三个 false,记录起始位置 break; // 找到第一个符合条件的位置后停止 } } if (startIndex !== -1) { // 如果找到了一个值为 false 的元素 targetPos = this.Container.nodes[startIndex].getWorldPosition().clone(); this.Container.node_isIdiom[startIndex] = true; console.log(targetPos); } else { console.log("没有空间了"); } break; case 2: { for (let i = 0; i < this.Container.unlock_Num - 1; i++) { if (this.Container.node_isIdiom[i] === false && this.Container.node_isIdiom[i + 1] === false) { startIndex = i; // 找到连续的两个 false,记录起始位置 break; // 找到第一个符合条件的位置后停止 } } if (startIndex !== -1) { console.log("找到连续的两个 false,起始索引是:", startIndex); // 可以在此使用 startIndex 进行后续操作,例如: let pos1 = this.Container.nodes[startIndex].getWorldPosition(); let pos2 = this.Container.nodes[startIndex + 1].getWorldPosition(); this.Container.node_isIdiom[startIndex] = true; this.Container.node_isIdiom[startIndex + 1] = true; targetPos.set( (pos1.x + pos2.x) / 2, (pos1.y + pos2.y) / 2, (pos1.z + pos2.z) / 2 ); console.log(targetPos); } break; } case 3: { for (let i = 0; i < this.Container.unlock_Num - 2; i++) { if (this.Container.node_isIdiom[i] === false && this.Container.node_isIdiom[i + 1] === false && this.Container.node_isIdiom[i + 2] === false) { startIndex = i; // 找到连续的三个 false,记录起始位置 break; // 找到第一个符合条件的位置后停止 } } if (startIndex !== -1) { // 找到连续三个 false,startIndex 即为最前面的索引 console.log("找到连续的三个 false,起始索引是:", startIndex); // 可以在此使用 startIndex 进行后续操作,例如: let pos1 = this.Container.nodes[startIndex].getWorldPosition(); let pos2 = this.Container.nodes[startIndex + 1].getWorldPosition(); let pos3 = this.Container.nodes[startIndex + 2].getWorldPosition(); this.Container.node_isIdiom[startIndex] = true; this.Container.node_isIdiom[startIndex + 1] = true; this.Container.node_isIdiom[startIndex + 2] = true; targetPos.set( (pos1.x + pos2.x + pos3.x) / 3, (pos1.y + pos2.y + pos3.y) / 3, (pos1.z + pos2.z + pos3.z) / 3 ); console.log(targetPos); } else { console.log("没有找到连续的三个 false"); } break; } default: return; } if (startIndex !== -1) { // node.getComponent(Cube_Infor).lock = true; node.getComponent(Cube_Infor).state = Cube_State.wait; node.getComponent(Cube_Infor).rigidbody.type = RigidBody.Type.STATIC; // 禁用重力 let targetRotation = new Quat(); Quat.fromEuler(targetRotation, -90, 0, 0); this.Container.canTouch=false; tween(node) .to(0.5, { position: new Vec3(targetPos.x, targetPos.y, targetPos.z + 0.4), rotation: targetRotation }) .call(() => { this.Container.idiom_combine.set(node.getComponent(Cube_Infor), startIndex); // 执行判断成语合成逻辑 let matchedCubes: Cube_Infor[] = []; let flag = this.Container.checkIdiom_Combine(node.getComponent(Cube_Infor), matchedCubes); if (flag) { // 执行合成动画 console.log("匹配的成语方块:", matchedCubes); this.combine_ani(matchedCubes[0], matchedCubes[1]); } else { //高亮 gui.get(UI_Idioms).light_Show(node.getComponent(Cube_Infor)); //判断槽子满了吗 let count = 0; for (let element of this.Container.node_isIdiom) { if (element == true) { count++; } } if (count == this.Container.unlock_Num) { gui.show(UI_LatticeFull); }else if(count>=this.Container.unlock_Num-2&&this.Container.unlock_Num!=9){ if(!this.Container.is_Show_UI_Lock) { gui.show(UI_Lock); this.Container.is_Show_UI_Lock=true; } } this.Container.canTouch=true; } }) .start(); } } //合成动画 combine_ani(cube1: Cube_Infor, cube2: Cube_Infor) { this.Container.canTouch=true; for (let i = this.Container.idiom_combine.get(cube1); i < this.Container.idiom_combine.get(cube1) + cube1.Text.length; i++) { this.Container.node_isIdiom[i] = false; } this.Container.idiom_combine.delete(cube1); for (let i = this.Container.idiom_combine.get(cube2); i < this.Container.idiom_combine.get(cube2) + cube2.Text.length; i++) { this.Container.node_isIdiom[i] = false; } this.Container.idiom_combine.delete(cube2); // 取消相关字的高亮显示 gui.get(UI_Idioms).light_Hide(cube1, cube2); gui.get(UI_Main).evt.emit(gui.get(UI_Main).evt.key.update_remain); this.adjustContainer(); // 检测容器中哪些字需要高亮显示 console.log(this.Container.node_isIdiom); // 在所有动画结束后执行 this.Container.idioms = this.Container.idioms.filter(c => c.idiom !== cube1.Text + cube2.Text); // 创建第一个 tween 动画 const tween1 = tween(cube1.node) .to(0.1, { position: new Vec3(this.Ani[0].position.x, this.Ani[0].position.y, this.Ani[0].position.z + 0.4) }) .call(() => { setTimeout(() => { cube1.state = Cube_State.dead; this.Container.recycleCube(cube1.node); }, 500.0); }); // 创建第二个 tween 动画 const tween2 = tween(cube2.node) .to(0.1, { position: new Vec3(this.Ani[1].position.x, this.Ani[1].position.y, this.Ani[1].position.z + 0.4) }) .call(() => { setTimeout(() => { cube2.state = Cube_State.dead; this.Container.recycleCube(cube2.node); }, 500.0); }); // 使用 tween 的并行组合功能 tween(cube1.node) .parallel(tween1, tween2) // 并行执行 tween1 和 tween2 .call(() => { Hall.getInstance().player.set_combine_num(1); }) .start(); } adjustContainer() { const container = this.Container; // 新的 node_isIdiom 状态数组 const newNodeIsIdiom = Array(container.node_isIdiom.length).fill(false); // 新的 idiom_combine 映射表 const newIdiomCombine = new Map(); // 遍历 idiom_combine,重新计算位置 for (const [cube, startIndex] of container.idiom_combine.entries()) { const txtLength = cube.Text.length; // 获取字长 let targetIndex = -1; // 目标位置起始索引 let targetPos = new Vec3(); switch (txtLength) { case 1: { // 找到一个空位 for (let i = 0; i < container.unlock_Num; i++) { if (!newNodeIsIdiom[i]) { targetIndex = i; break; } } if (targetIndex !== -1) { targetPos = container.nodes[targetIndex].getWorldPosition().clone(); newNodeIsIdiom[targetIndex] = true; // 占用位置 } else { console.log("没有空位容纳单字 Cube_Infor"); } break; } case 2: { // 找到连续两个空位 for (let i = 0; i < container.unlock_Num - 1; i++) { if (!newNodeIsIdiom[i] && !newNodeIsIdiom[i + 1]) { targetIndex = i; break; } } if (targetIndex !== -1) { const pos1 = container.nodes[targetIndex].getWorldPosition(); const pos2 = container.nodes[targetIndex + 1].getWorldPosition(); targetPos.set( (pos1.x + pos2.x) / 2, (pos1.y + pos2.y) / 2, (pos1.z + pos2.z) / 2 ); newNodeIsIdiom[targetIndex] = true; newNodeIsIdiom[targetIndex + 1] = true; } else { console.log("没有连续两个空位容纳双字 Cube_Infor"); } break; } case 3: { // 找到连续三个空位 for (let i = 0; i < container.unlock_Num - 2; i++) { if ( !newNodeIsIdiom[i] && !newNodeIsIdiom[i + 1] && !newNodeIsIdiom[i + 2] ) { targetIndex = i; break; } } if (targetIndex !== -1) { const pos1 = container.nodes[targetIndex].getWorldPosition(); const pos2 = container.nodes[targetIndex + 1].getWorldPosition(); const pos3 = container.nodes[targetIndex + 2].getWorldPosition(); targetPos.set( (pos1.x + pos2.x + pos3.x) / 3, (pos1.y + pos2.y + pos3.y) / 3, (pos1.z + pos2.z + pos3.z) / 3 ); newNodeIsIdiom[targetIndex] = true; newNodeIsIdiom[targetIndex + 1] = true; newNodeIsIdiom[targetIndex + 2] = true; } else { console.log("没有连续三个空位容纳三字 Cube_Infor"); } break; } default: return; } // 移动 Cube_Infor 到目标位置 if (targetIndex !== -1) { tween(cube.node) .to(0.3, { position: new Vec3(targetPos.x, targetPos.y, targetPos.z + 0.4) }) .start(); newIdiomCombine.set(cube, targetIndex); // 更新新映射 } } // 更新 container 状态 container.node_isIdiom = newNodeIsIdiom; container.idiom_combine = newIdiomCombine; console.log("调整后的容器状态:", container.node_isIdiom); console.log("更新后的 idiom_combine:", [...container.idiom_combine.entries()]); } async UnLock(node: Node) { const res = await chsdk.playRewardAd('解锁槽位'); if (res) { node.active = false; this.Container.unlock_Num += 1; } } }