Files
cocos/assets/scripts/ui/LevelSwitchBar.ts
刘宇飞 d393302388 Complete Cocos Creator port with level bundles, themes, and tooling.
Adds level prefabs, theme assets, audio, extensions, and deployment scripts for the Unity WebGL migration.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 15:30:58 +08:00

162 lines
6.2 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {
_decorator, Component, Node, Label, EditBox, Button, UITransform, Color, Widget,
} from 'cc';
import { GameManager } from '../manager/GameManager';
import { getMaxLevelId, getMinLevelId } from '../level/LevelRegistry';
const { ccclass } = _decorator;
/**
* 预览/运行时的关卡切换条(真实 Button不依赖 Inspector 扩展)
*/
@ccclass('LevelSwitchBar')
export class LevelSwitchBar extends Component {
private editBox: EditBox | null = null;
static ensure(parent: Node): LevelSwitchBar {
let bar = parent.getChildByName('LevelSwitchBar');
if (!bar) {
bar = new Node('LevelSwitchBar');
bar.parent = parent;
bar.addComponent(LevelSwitchBar);
}
return bar.getComponent(LevelSwitchBar)!;
}
onLoad() {
this.buildUI();
}
private buildUI() {
const rootUi = this.node.getComponent(UITransform) || this.node.addComponent(UITransform);
rootUi.setContentSize(520, 48);
const hint = this.node.getChildByName('HintLabel') ?? new Node('HintLabel');
hint.parent = this.node;
const hintUi = hint.getComponent(UITransform) || hint.addComponent(UITransform);
hintUi.setContentSize(200, 36);
hint.setPosition(-160, 0, 0);
const hintLabel = hint.getComponent(Label) || hint.addComponent(Label);
hintLabel.string = `关卡 ${getMinLevelId()}${getMaxLevelId()}`;
hintLabel.fontSize = 18;
hintLabel.color = new Color(200, 220, 255);
let inputNode = this.node.getChildByName('LevelInput');
if (!inputNode) {
inputNode = new Node('LevelInput');
inputNode.parent = this.node;
}
inputNode.setPosition(-20, 0, 0);
const inputUi = inputNode.getComponent(UITransform) || inputNode.addComponent(UITransform);
inputUi.setContentSize(80, 36);
this.editBox = inputNode.getComponent(EditBox) || inputNode.addComponent(EditBox);
this.editBox.placeholder = '关卡号';
this.editBox.string = '1';
this.editBox.fontSize = 20;
this.editBox.textLabel = this.ensureEditLabel(inputNode);
this.editBox.placeholderLabel = this.ensurePlaceholderLabel(inputNode);
let btnNode = this.node.getChildByName('BtnSwitchLevel');
if (!btnNode) {
btnNode = new Node('BtnSwitchLevel');
btnNode.parent = this.node;
}
btnNode.setPosition(120, 0, 0);
const btnUi = btnNode.getComponent(UITransform) || btnNode.addComponent(UITransform);
btnUi.setContentSize(140, 40);
const btn = btnNode.getComponent(Button) || btnNode.addComponent(Button);
btn.transition = Button.Transition.SCALE;
const btnLabel = this.ensureButtonLabel(btnNode);
btnLabel.string = '切换关卡';
btnLabel.fontSize = 20;
btnLabel.color = new Color(255, 255, 255);
btn.node.off(Button.EventType.CLICK);
btn.node.on(Button.EventType.CLICK, this.onClickSwitch, this);
let prevNode = this.node.getChildByName('BtnPrev');
if (!prevNode) {
prevNode = new Node('BtnPrev');
prevNode.parent = this.node;
}
prevNode.setPosition(200, 0, 0);
prevNode.getComponent(UITransform) || prevNode.addComponent(UITransform).setContentSize(56, 36);
const prevBtn = prevNode.getComponent(Button) || prevNode.addComponent(Button);
const prevLbl = this.ensureButtonLabel(prevNode);
prevLbl.string = '◀';
prevLbl.fontSize = 22;
prevNode.off(Button.EventType.CLICK);
prevNode.on(Button.EventType.CLICK, () => GameManager.instance?.prevLevel(), this);
let nextNode = this.node.getChildByName('BtnNext');
if (!nextNode) {
nextNode = new Node('BtnNext');
nextNode.parent = this.node;
}
nextNode.setPosition(248, 0, 0);
nextNode.getComponent(UITransform) || nextNode.addComponent(UITransform).setContentSize(56, 36);
const nextBtn = nextNode.getComponent(Button) || nextNode.addComponent(Button);
const nextLbl = this.ensureButtonLabel(nextNode);
nextLbl.string = '▶';
nextLbl.fontSize = 22;
nextNode.off(Button.EventType.CLICK);
nextNode.on(Button.EventType.CLICK, () => GameManager.instance?.nextLevel(), this);
const widget = this.node.getComponent(Widget) || this.node.addComponent(Widget);
widget.isAlignTop = true;
widget.top = 12;
widget.isAlignHorizontalCenter = true;
widget.alignMode = Widget.AlignMode.ON_WINDOW_RESIZE;
}
syncFromManager() {
const gm = GameManager.instance;
if (!gm || !this.editBox) return;
this.editBox.string = gm.inputLevel || String(gm.curLevelID);
}
private onClickSwitch() {
const gm = GameManager.instance;
if (!gm) {
console.warn('[LevelSwitchBar] GameManager 未就绪');
return;
}
if (this.editBox) {
gm.inputLevel = this.editBox.string.trim();
}
gm.clickSwitchLevel();
this.syncFromManager();
}
private ensureButtonLabel(btnNode: Node): Label {
let t = btnNode.getChildByName('Label');
if (!t) {
t = new Node('Label');
t.parent = btnNode;
t.addComponent(UITransform).setContentSize(140, 40);
}
return t.getComponent(Label) || t.addComponent(Label);
}
private ensureEditLabel(parent: Node): Label {
let t = parent.getChildByName('TEXT_LABEL');
if (!t) {
t = new Node('TEXT_LABEL');
t.parent = parent;
t.addComponent(UITransform).setContentSize(80, 36);
}
return t.getComponent(Label) || t.addComponent(Label);
}
private ensurePlaceholderLabel(parent: Node): Label {
let t = parent.getChildByName('PLACEHOLDER_LABEL');
if (!t) {
t = new Node('PLACEHOLDER_LABEL');
t.parent = parent;
t.addComponent(UITransform).setContentSize(80, 36);
}
const lb = t.getComponent(Label) || t.addComponent(Label);
lb.color = new Color(160, 160, 160);
return lb;
}
}