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:
153
extensions/level-map-editor/dist/editor-tools.js
vendored
Normal file
153
extensions/level-map-editor/dist/editor-tools.js
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
'use strict';
|
||||
|
||||
const TOOLS = ['paint', 'box', 'picker', 'eraser', 'fill'];
|
||||
|
||||
const TOOL_LABELS = {
|
||||
paint: '画笔:在网格上点击或拖拽绘制(需先在右侧选瓦片)',
|
||||
box: '框选:拖拽矩形区域,松开后用当前瓦片填满',
|
||||
picker: '吸管:点击已有格子,吸取瓦片为当前画笔',
|
||||
eraser: '橡皮擦:点击或拖拽删除当前层的格子',
|
||||
fill: '油漆桶:填充相连的同类型格子(需先选瓦片)',
|
||||
};
|
||||
|
||||
const TOOL_CURSORS = {
|
||||
paint: 'crosshair',
|
||||
box: 'crosshair',
|
||||
picker: 'copy',
|
||||
eraser: 'not-allowed',
|
||||
fill: 'cell',
|
||||
};
|
||||
|
||||
function layerMap(state) {
|
||||
return state.editLayer === 'ground' ? state.config.ground : state.config.border;
|
||||
}
|
||||
|
||||
function getCell(state, key) {
|
||||
const map = layerMap(state);
|
||||
return map[key];
|
||||
}
|
||||
|
||||
function hasCell(state, key) {
|
||||
return getCell(state, key) !== undefined;
|
||||
}
|
||||
|
||||
function removeCell(state, key) {
|
||||
if (state.editLayer === 'ground') delete state.config.ground[key];
|
||||
else delete state.config.border[key];
|
||||
}
|
||||
|
||||
function setCell(state, key, tileKey) {
|
||||
if (state.editLayer === 'ground') state.config.ground[key] = tileKey;
|
||||
else state.config.border[key] = tileKey;
|
||||
}
|
||||
|
||||
function canPaintBrush(state) {
|
||||
return state.brush && state.brush.layer === state.editLayer;
|
||||
}
|
||||
|
||||
function fillRectangle(state, x0, y0, x1, y1, tileKey) {
|
||||
const minX = Math.min(x0, x1);
|
||||
const maxX = Math.max(x0, x1);
|
||||
const minY = Math.min(y0, y1);
|
||||
const maxY = Math.max(y0, y1);
|
||||
let n = 0;
|
||||
for (let x = minX; x <= maxX; x++) {
|
||||
for (let y = minY; y <= maxY; y++) {
|
||||
setCell(state, `${x},${y}`, tileKey);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
function eraseRectangle(state, x0, y0, x1, y1) {
|
||||
const minX = Math.min(x0, x1);
|
||||
const maxX = Math.max(x0, x1);
|
||||
const minY = Math.min(y0, y1);
|
||||
const maxY = Math.max(y0, y1);
|
||||
let n = 0;
|
||||
for (let x = minX; x <= maxX; x++) {
|
||||
for (let y = minY; y <= maxY; y++) {
|
||||
const key = `${x},${y}`;
|
||||
if (hasCell(state, key)) {
|
||||
removeCell(state, key);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/** 四连通洪水填充(仅当前编辑层) */
|
||||
function floodFill(state, startKey, fillTileKey) {
|
||||
const map = layerMap(state);
|
||||
const target = map[startKey];
|
||||
if (target === fillTileKey) return 0;
|
||||
const q = [startKey];
|
||||
const seen = new Set([startKey]);
|
||||
let n = 0;
|
||||
while (q.length) {
|
||||
const key = q.shift();
|
||||
map[key] = fillTileKey;
|
||||
n++;
|
||||
const [xs, ys] = key.split(',');
|
||||
const x = parseInt(xs, 10);
|
||||
const y = parseInt(ys, 10);
|
||||
for (const [nx, ny] of [[x + 1, y], [x - 1, y], [x, y + 1], [x, y - 1]]) {
|
||||
const nk = `${nx},${ny}`;
|
||||
if (seen.has(nk)) continue;
|
||||
const v = map[nk];
|
||||
const same = target === undefined ? v === undefined : v === target;
|
||||
if (!same) continue;
|
||||
seen.add(nk);
|
||||
q.push(nk);
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/** 洪水清除(橡皮擦油漆桶:删相连同值区域) */
|
||||
function floodErase(state, startKey) {
|
||||
const map = layerMap(state);
|
||||
if (map[startKey] === undefined) return 0;
|
||||
const target = map[startKey];
|
||||
const q = [startKey];
|
||||
const seen = new Set([startKey]);
|
||||
let n = 0;
|
||||
while (q.length) {
|
||||
const key = q.shift();
|
||||
delete map[key];
|
||||
n++;
|
||||
const [xs, ys] = key.split(',');
|
||||
const x = parseInt(xs, 10);
|
||||
const y = parseInt(ys, 10);
|
||||
for (const [nx, ny] of [[x + 1, y], [x - 1, y], [x, y + 1], [x, y - 1]]) {
|
||||
const nk = `${nx},${ny}`;
|
||||
if (seen.has(nk) || map[nk] !== target) continue;
|
||||
seen.add(nk);
|
||||
q.push(nk);
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
function findPaletteTile(state, tileKey, layer) {
|
||||
return state.tiles.find((t) => t.tileKey === tileKey && t.layer === layer) || null;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
TOOLS,
|
||||
TOOL_LABELS,
|
||||
TOOL_CURSORS,
|
||||
layerMap,
|
||||
getCell,
|
||||
hasCell,
|
||||
removeCell,
|
||||
setCell,
|
||||
canPaintBrush,
|
||||
fillRectangle,
|
||||
eraseRectangle,
|
||||
floodFill,
|
||||
floodErase,
|
||||
findPaletteTile,
|
||||
};
|
||||
Reference in New Issue
Block a user