Adds level prefabs, theme assets, audio, extensions, and deployment scripts for the Unity WebGL migration. Co-authored-by: Cursor <cursoragent@cursor.com>
97 lines
3.1 KiB
TypeScript
97 lines
3.1 KiB
TypeScript
import { Layers, Node, Sprite, UITransform, Vec3 } from 'cc';
|
|
import { cellToWorldCenter, parseCellKey, tileNodeName } from '../core/GridCoords';
|
|
import { LevelConfig } from './LevelTypes';
|
|
import { setupLayerContainer } from './TileLayout';
|
|
|
|
const UI_LAYER = Layers.Enum.UI_2D;
|
|
|
|
function ensureLayer(root: Node, name: 'Ground' | 'Border'): Node {
|
|
let layer = root.getChildByName(name);
|
|
if (!layer) {
|
|
layer = new Node(name);
|
|
layer.parent = root;
|
|
layer.layer = UI_LAYER;
|
|
}
|
|
setupLayerContainer(layer);
|
|
return layer;
|
|
}
|
|
|
|
function ensureTile(layer: Node, layerKind: 'ground' | 'border', x: number, y: number): Node {
|
|
const nodeName = tileNodeName(layerKind, x, y);
|
|
let node = layer.getChildByName(nodeName);
|
|
if (!node) {
|
|
node = new Node(nodeName);
|
|
node.parent = layer;
|
|
node.layer = UI_LAYER;
|
|
node.addComponent(UITransform);
|
|
node.addComponent(Sprite);
|
|
}
|
|
node.active = true;
|
|
return node;
|
|
}
|
|
|
|
/** 按 levels-database.json 补齐 / 隐藏砖块节点(与关卡编辑器数据一致) */
|
|
export function syncTileNodesFromConfig(levelRoot: Node, config: LevelConfig): number {
|
|
const ground = ensureLayer(levelRoot, 'Ground');
|
|
const border = ensureLayer(levelRoot, 'Border');
|
|
const wantGround = new Set(Object.keys(config.ground ?? {}));
|
|
const wantBorder = new Set(Object.keys(config.border ?? {}));
|
|
let n = 0;
|
|
|
|
for (const key of wantGround) {
|
|
const p = parseCellKey(key);
|
|
if (!p) continue;
|
|
ensureTile(ground, 'ground', p.x, p.y);
|
|
n++;
|
|
}
|
|
for (const key of wantBorder) {
|
|
const p = parseCellKey(key);
|
|
if (!p) continue;
|
|
ensureTile(border, 'border', p.x, p.y);
|
|
n++;
|
|
}
|
|
|
|
for (const ch of ground.children) {
|
|
const m = /^g_(-?\d+)_(-?\d+)$/.exec(ch.name);
|
|
if (!m) continue;
|
|
const key = `${m[1]},${m[2]}`;
|
|
ch.active = wantGround.has(key);
|
|
}
|
|
for (const ch of border.children) {
|
|
const m = /^b_(-?\d+)_(-?\d+)$/.exec(ch.name);
|
|
if (!m) continue;
|
|
const key = `${m[1]},${m[2]}`;
|
|
ch.active = wantBorder.has(key);
|
|
}
|
|
return n;
|
|
}
|
|
|
|
/** 关卡包围盒中心(格子 pivot 落点),用于居中显示 */
|
|
export function computeLevelCenterOffset(config: LevelConfig): Vec3 {
|
|
const keys = [
|
|
...Object.keys(config.ground ?? {}),
|
|
...Object.keys(config.border ?? {}),
|
|
];
|
|
if (!keys.length) return new Vec3(0, 0, 0);
|
|
|
|
let minX = Infinity;
|
|
let maxX = -Infinity;
|
|
let minY = Infinity;
|
|
let maxY = -Infinity;
|
|
for (const key of keys) {
|
|
const p = parseCellKey(key);
|
|
if (!p) continue;
|
|
const w = cellToWorldCenter(new Vec3(p.x, p.y, 0));
|
|
minX = Math.min(minX, w.x);
|
|
maxX = Math.max(maxX, w.x);
|
|
minY = Math.min(minY, w.y);
|
|
maxY = Math.max(maxY, w.y);
|
|
}
|
|
return new Vec3(-(minX + maxX) * 0.5, -(minY + maxY) * 0.5, 0);
|
|
}
|
|
|
|
export function centerLevelRoot(levelRoot: Node, config: LevelConfig) {
|
|
const off = computeLevelCenterOffset(config);
|
|
levelRoot.setPosition(off.x, off.y, 0);
|
|
}
|