| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431 |
- 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<event_protocol>();
- 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<Layout_Main>();
- 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<Layout_Main>();
- 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
- }
|