import { _decorator, Component, director, Color, Label, Node } from 'cc'; import { ConfigMgr } from '../data/ConfigMgr'; import { CCJsonLoader } from './CCJsonLoader'; import { LevelMgr } from '../logic/LevelMgr'; import { ensureCanvasSize, createLabel } from './MainMenuEntry'; import { DESIGN_HEIGHT } from '../common/Constants'; const { ccclass, property } = _decorator; /** * Generic Level scene entry (task 7.1-7.2 hookup). * * Attach to the root node of `Level_1_1` … `Level_1_5`. Configure the * `levelId` property in the Inspector ("1-1", "1-2", ...). * * For MVP the scene has no real gameplay rendering yet; `autoBuildUI` * simply draws a top-centered label with the current level id so you can * verify scene transitions by eye. */ @ccclass('LevelEntry') export class LevelEntry extends Component { @property({ tooltip: '本关的 levelId (与 configs/levels.json 对应),如 1-1 / 1-2 / 1-3 / 1-4 / 1-5' }) public levelId: string = '1-1'; @property({ tooltip: '胜利后跳转的场景,留空则按 1-1 → 1-2 → ... → 1-5 → Boss 自动推导' }) public nextSceneName: string = ''; @property({ tooltip: '是否自动创建关卡 HUD (顶部显示 Level / 倒计时)' }) public autoBuildUI: boolean = true; private mgr: LevelMgr | undefined; private hudNode: Node | null = null; protected async onLoad(): Promise { if (this.autoBuildUI) this.buildDefaultUI(); const cfg = new ConfigMgr(new CCJsonLoader()); await cfg.load(); this.mgr = new LevelMgr(cfg.level(this.levelId)); } protected update(dt: number): void { if (!this.mgr) return; const status = this.mgr.tick(dt); this.refreshHud(); if (status === 'victory') { director.loadScene(this.nextSceneName || this.deriveNextScene()); } else if (status === 'timeout' || status === 'player_dead') { director.loadScene('Settlement'); } } private deriveNextScene(): string { const map: Record = { '1-1': 'Level_1_2', '1-2': 'Level_1_3', '1-3': 'Level_1_4', '1-4': 'Level_1_5', '1-5': 'Boss_ShuangHuanFang', }; return map[this.levelId] ?? 'Settlement'; } private buildDefaultUI(): void { ensureCanvasSize(this.node); createLabel(this.node, `Level ${this.levelId}`, 0, DESIGN_HEIGHT / 2 - 50, 28, Color.WHITE); this.hudNode = createLabel( this.node, 'Time: --', 0, DESIGN_HEIGHT / 2 - 90, 22, new Color(255, 220, 120, 255), ); } private refreshHud(): void { if (!this.hudNode || !this.mgr) return; const lb = this.hudNode.getComponent(Label); if (lb) { const r = this.mgr.result(); lb.string = `Time: ${Math.max(0, Math.ceil(r.remainingSec))}s Kills: ${Object.values(r.kills).reduce((a, b) => a + b, 0)}`; } } }