import { _decorator, Component, director, game, instantiate, Label, Node, NodePool, PhysicsSystem2D, randomRangeInt, Scene, Scheduler, Sprite, SpriteFrame, v3, Vec3 } from 'cc'; import { GameUILayers, gui } from 'db://assets/core/ui/ui'; import ui_base from 'db://assets/core/ui/ui_base'; import { ModuleDef } from 'db://assets/Script/ModuleDef'; import { Layout_Main } from './Layout_Main'; import { UI_Settings } from '../UI_Settings/UI_Settings'; import { skin_res } from '../../game/link/skin/skin_res'; import { BlockLink } from '../../game/link/block/BlockLink'; import { ch } from 'db://assets/ch/ch'; import { UI_Win } from '../UI_Win/UI_Win'; import { LvData } from '../../game/LvData/LvData'; import { UI_Lose } from '../UI_Lose/UI_Lose'; import { Stone } from '../../game/tui/stone/Stone'; import { Role } from '../../game/tui/role/Role'; import { GameState } from '../../game/GameState'; import { audioManager } from '../../Audio/AudioManager'; import { Hall } from '../../hall/Hall'; import { data_type } from '../../game/PlayerData'; const { ccclass, property } = _decorator; interface event_protocol { pause(): void;//游戏暂停 resume(): void;//游戏恢复 next_level(): void;//下一关 } @ccclass('UI_Main') export class UI_Main extends ui_base { public lt: Layout_Main; public static lt: Layout_Main; lv = Hall.getInstance().player.data.get(data_type.max_floor) public evt = ch.get_new_event(); running = true; constructor() { super(ModuleDef.GAME, 'ui/main/main', GameUILayers.GAME, Layout_Main); } private _stone: number = 0;//掉落的石頭 private totalStones: number = 120; // 总石头数量 static blockArry: Node[][] = []; //石头对象池 private _stonePool: NodePool; private _activeStones: Node[] = []; //方块对象池 private _blockPool: NodePool; private _activeBlocks: Node[] = []; private _paused: boolean = false; get is_paused(): boolean { return this._paused; } protected async onCreated() { audioManager.play('sound/bgm'); this.lt = this.getLayout(); UI_Main.lt = this.lt; this.onButtonEvent(UI_Main.lt.setBtn, () => { gui.show(UI_Settings); this.pause(); }, this); this._stonePool = new NodePool('Stone'); this.preloadStonePool(50); // 预加载50个石头 this.init() this.evt.on(this.evt.key.pause, this.pause, this); this.evt.on(this.evt.key.resume, this.resume, this); this.evt.on(this.evt.key.next_level, this.new_level, this); } public pause(): void { this._paused = true; // DirectorUtil.pause(); UI_Main.lt.title.set_stop(); } // public resume(): void { this._paused = false; // DirectorUtil.resume(); UI_Main.lt.title.set_resume(); } init() { for (let i = 0; i < 20; i++) { this.lt.scheduleOnce(() => { this.creatorStone(10);//石头 }, i * 0.1) } this.creatorBlock();//llk UI_Main.lt.role.init(endPos.time) UI_Main.lt.pushItem.init(endPos.time) this.setingLV(); } new_level() { this.setingLV(); this.close(); Hall.getInstance().to_main(); } setingLV() { const layout = this.getLayout(); debugger let currentLevel = this.lv; // 从存档读取当前关卡 if (currentLevel <= 0) { currentLevel = 1; } UI_Main.lt.Level.string = currentLevel.toString(); const passedLevels = currentLevel - 1; const group = Math.floor(passedLevels / 4); const unlockPos = passedLevels % 4; // 动态控制循环次数,避免越界 const maxCircles = Math.min(layout.LevelNum.length, 4); for (let i = 0; i < maxCircles; i++) { const num = group * 4 + 1 + i; layout.LevelNum[i].string = num.toString(); // 新组起始关(第5关)时强制解锁第一个节点 const isNewGroupStart = unlockPos === 0 && passedLevels > 0; const shouldUnlock = isNewGroupStart ? i === 0 : i <= unlockPos; layout.LevelNode[i].active = shouldUnlock; } } addStone(count: number) { this._stone += count this.flash(); this.checkVictory(); } flash() { UI_Main.lt.title.filled(this._stone) } checkVictory() { const remainingTime = UI_Main.lt.title.getRemainingTime(); if (this._stone == this.totalStones && remainingTime > 0) { console.log("游戏胜利!"); // 更新 Hall.getInstance().player.data.add(data_type.max_floor, 1); Hall.getInstance().player.setDirty(); Hall.getInstance().player.save_rank_floor(); Hall.getInstance().player.save_Province_floor(); Hall.getInstance().player.save(); gui.show(UI_Win); UI_Main.lt.title.unschedule(UI_Main.lt.title.updateTime); UI_Main.lt.unscheduleAllCallbacks(); // 停止所有update } else if (this._stone < this.totalStones && remainingTime < 0) { console.log("游戏失败!"); gui.show(UI_Lose); } } public async creatorBlock() { const startX = -315; const startY = 40; const spacing = 70; const tempBlock = instantiate(UI_Main.lt.block); const blockProto = tempBlock.getChildByName("icon").getComponent(skin_res); let allSkins: SpriteFrame[] = []; // 获取skin4的唯一图片 const skin4Image = blockProto.skin4[0]; if (LvData.instance.fkpf == 1) { allSkins = [ ...blockProto.skin1, ...blockProto.skin2, ...blockProto.skin3 ].slice(0, 21); // 使用前21种皮肤 } else if (LvData.instance.fkpf == 2) { allSkins = [ ...blockProto.skin5, ...blockProto.skin6, ...blockProto.skin7 ].slice(0, 21); // 使用前21种皮肤 } else if (LvData.instance.fkpf == 3) { allSkins = [ ...blockProto.skin8, ...blockProto.skin9, ...blockProto.skin10 ].slice(0, 21); } else if (LvData.instance.fkpf == 4) { allSkins = [ ...blockProto.skin11, ...blockProto.skin12, ...blockProto.skin13 ].slice(0, 21); // 使用前21种皮肤 } tempBlock.destroy(); // 生成随机皮肤对(48对=96个) let requiredSkins: SpriteFrame[] = []; for (let i = 0; i < 48; i++) { const skin = allSkins[Math.floor(Math.random() * allSkins.length)]; requiredSkins.push(skin, skin); // 成对添加 } // 添加2对(4个)skin4图片 requiredSkins.push(skin4Image, skin4Image); // 第一对 requiredSkins.push(skin4Image, skin4Image); // 第二对 // 洗牌算法 const shuffleArray = (array: SpriteFrame[]) => { for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array; }; // 打乱顺序 const shuffledSkins = shuffleArray([...requiredSkins]); // 创建10x10网格 const grid: SpriteFrame[][] = Array(10).fill(null).map(() => Array(10).fill(null)); // 填充网格并避免相邻相同 for (let y = 0; y < 10; y++) { for (let x = 0; x < 10; x++) { const index = y * 10 + x; let skin = shuffledSkins[index]; // 检查左邻居和上邻居 const neighbors: SpriteFrame[] = []; if (x > 0) neighbors.push(grid[y][x - 1]); // 左邻居 if (y > 0) neighbors.push(grid[y - 1][x]); // 上邻居 // 如果与邻居相同,尝试交换后续皮肤 if (neighbors.some(n => n === skin)) { for (let swapIndex = index + 1; swapIndex < shuffledSkins.length; swapIndex++) { const candidate = shuffledSkins[swapIndex]; if (neighbors.indexOf(candidate) === -1) { // 交换皮肤 [shuffledSkins[index], shuffledSkins[swapIndex]] = [shuffledSkins[swapIndex], shuffledSkins[index]]; skin = shuffledSkins[index]; break; } } } grid[y][x] = skin; } } // 创建对象池 if (!this._blockPool) { this._blockPool = new NodePool('Block'); } // 清空现有方块 this.clearAllBlocks(); for (let y = 0; y < 10; y++) { BlockLink.blockArry[y] = []; for (let x = 0; x < 10; x++) { let blockInstance: Node; // 从对象池获取或创建 if (this._blockPool.size() > 0) { blockInstance = this._blockPool.get(); } else { blockInstance = instantiate(UI_Main.lt.block); } const icon = blockInstance.getChildByName("icon")?.getComponent(Sprite); const blockicon = blockInstance.getComponent(Sprite) const blockProto = blockInstance.getChildByName("icon").getComponent(skin_res); if (LvData.instance.fkpf == 1) { blockicon.spriteFrame = blockProto.fk1[0] } else if (LvData.instance.fkpf == 2) { blockicon.spriteFrame = blockProto.fk2[0] } else if (LvData.instance.fkpf == 3) { blockicon.spriteFrame = blockProto.fk3[0] } else if (LvData.instance.fkpf == 4) { blockicon.spriteFrame = blockProto.fk4[0] } if (icon) { icon.spriteFrame = grid[y][x]; // 使用网格中的皮肤 } const posX = startX + x * spacing; const posY = startY - y * spacing; blockInstance.setPosition(posX, posY); blockInstance.active = true; UI_Main.lt.blockNode.addChild(blockInstance); BlockLink.blockArry[y][x] = blockInstance; this._activeBlocks.push(blockInstance); } } BlockLink.totalBlocks = 100; BlockLink.remainingBlocks = BlockLink.totalBlocks; } // 回收方块 public recycleBlock(blockNode: Node) { blockNode.active = false; UI_Main.lt.blockNode.removeChild(blockNode); this._blockPool.put(blockNode); // 从活动列表中移除 const index = this._activeBlocks.indexOf(blockNode); if (index !== -1) { this._activeBlocks.splice(index, 1); } } // 清空所有方块 public clearAllBlocks() { while (this._activeBlocks.length > 0) { this.recycleBlock(this._activeBlocks[0]); } BlockLink.blockArry = []; } // 预加载对象池 preloadStonePool(count: number) { for (let i = 0; i < count; i++) { const stone = instantiate(UI_Main.lt.stone); stone.getComponent(Stone)?.init(this); // stone.getComponent(Stone)?.init(this,GameState.inst.spf[0]); this.returnStoneToPool(stone); } } private getStoneFromPool(): Node | null { if (this._stonePool.size() > 0) { return this._stonePool.get(); } return null; } private returnStoneToPool(stoneNode: Node) { stoneNode.active = false; this._stonePool.put(stoneNode); } //创建石头 public async creatorStone(count: number) { //debugger const centerPos = new Vec3(0, 0, 0); for (let i = 0; i < count; i++) { let stoneInstance: Node = null; if (this._stonePool.size() > 0) { stoneInstance = this._stonePool.get() } else { stoneInstance = instantiate(UI_Main.lt.stone); stoneInstance.getComponent(Stone)?.init(this); // 传递UI_Main引用 } const blockProto = stoneInstance.getComponent(Stone); const blockiconSprite = stoneInstance.getComponent(Sprite) if (LvData.instance.stpf == 1) { blockiconSprite.spriteFrame = blockProto.stoneSkin1[0] } else if (LvData.instance.stpf == 2) { blockiconSprite.spriteFrame = blockProto.stoneSkin2[0] } else if (LvData.instance.stpf == 3) { blockiconSprite.spriteFrame = blockProto.stoneSkin3[0] } else if (LvData.instance.stpf == 4) { blockiconSprite.spriteFrame = blockProto.stoneSkin4[0] } let scale = Math.random() * 0.3 + 0.8 stoneInstance.scale = v3(scale, scale, 1) //在stoneNode的位置附近偏移 const offsetX = randomRangeInt(-5, 5); // 水平方向随机偏移 const offsetY = randomRangeInt(-2, 2); // 垂直方向随机偏移 const spawnPos = new Vec3( centerPos.x + offsetX, centerPos.y + offsetY, centerPos.z ); stoneInstance.active = true; UI_Main.lt.stoneNode.addChild(stoneInstance); this._activeStones.push(stoneInstance); stoneInstance.setPosition(spawnPos); } } // 回收石头到对象池 public recycleStone(stoneNode: Node) { stoneNode.active = false; UI_Main.lt.stoneNode.removeChild(stoneNode); this._stonePool.put(stoneNode); // 从活动列表中移除 const index = this._activeStones.indexOf(stoneNode); if (index !== -1) { this._activeStones.splice(index, 1); } this.addStone(1); } // 清空所有石头 public clearAllStones() { while (this._activeStones.length > 0) { this.recycleStone(this._activeStones[0]); } } protected onUpdate(dt: number) { UI_Main.lt.role.doMove(dt); UI_Main.lt.pushItem.resize(dt) } public static get role(): Role { return UI_Main.lt.role; } } export const endPos = { // 终点 role: v3(-200, 220), pushItem: 500, ballEndY: -1200, time: 150 }