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>
This commit is contained in:
2026-06-16 15:30:58 +08:00
parent cba5105908
commit d393302388
6248 changed files with 17322729 additions and 11036 deletions

View File

@@ -0,0 +1,161 @@
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;
}
}