Files
cocos/assets/scripts/level/LevelTileSync.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

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);
}