Files
cocos/assets/scripts/core/GridCoords.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

89 lines
2.9 KiB
TypeScript
Raw 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 { Vec3 } from 'cc';
import { CELL_PIXEL } from './GridConstants';
/**
* 与 Unity Grid 一致CellLayout Isometric Z-as-YCellSize (1, 0.5, 1)。
* 缩放后 halfW=CELL/2, halfH=CELL/4。
*/
const HALF_W = CELL_PIXEL * 0.5;
const HALF_H = CELL_PIXEL * 0.25;
if (!Number.isFinite(HALF_W) || HALF_W <= 0) {
console.error('[GridCoords] CELL_PIXEL 无效,请检查 GridConstants 模块加载');
}
export function cellToWorld(cell: Vec3): Vec3 {
const x = cell.x;
const y = cell.y;
return new Vec3((x - y) * HALF_W, (x + y) * HALF_H, 0);
}
/** Unity Tilemap tileAnchor (0.5,0.5):精灵 pivot 对齐格子中心 */
export function cellToWorldCenter(cell: Vec3): Vec3 {
const w = cellToWorld(cell);
return new Vec3(w.x, w.y + HALF_H, 0);
}
export function worldToCell(world: Vec3): Vec3 {
const cx = (world.y / HALF_H + world.x / HALF_W) * 0.5;
const cy = (world.y / HALF_H - world.x / HALF_W) * 0.5;
return new Vec3(Math.round(cx), Math.round(cy), 0);
}
/** 输入为世界坐标下的格子中心(与 Tilemap tileAnchor 一致) */
export function worldCenterToCell(world: Vec3): Vec3 {
return worldToCell(new Vec3(world.x, world.y - HALF_H, world.z));
}
/** 世界坐标吸附到最近格子中心 */
export function snapWorldToCellCenter(world: Vec3, out?: Vec3): Vec3 {
const cell = worldToCell(world);
const snapped = cellToWorld(cell);
if (out) {
out.set(snapped);
return out;
}
return snapped;
}
export function formatCellKey(x: number, y: number): string {
return `${x},${y}`;
}
export function parseCellKey(key: string): { x: number; y: number } | null {
const parts = key.split(',');
if (parts.length !== 2) return null;
const x = parseInt(parts[0], 10);
const y = parseInt(parts[1], 10);
if (Number.isNaN(x) || Number.isNaN(y)) return null;
return { x, y };
}
/** 烘焙瓦片节点名 g_1_0 / b_-2_1 → 格子坐标 */
export function parseTileNodeName(name: string | undefined | null): { layer: 'ground' | 'border'; x: number; y: number } | null {
if (!name) return null;
const m = name.match(/^([gb])_(-?\d+)_(-?\d+)$/);
if (!m) return null;
return {
layer: m[1] === 'g' ? 'ground' : 'border',
x: parseInt(m[2], 10),
y: parseInt(m[3], 10),
};
}
export function tileNodeName(layer: 'ground' | 'border', x: number, y: number): string {
const p = layer === 'ground' ? 'g' : 'b';
return `${p}_${x}_${y}`;
}
export function getHalfCellSize(): { halfW: number; halfH: number } {
return { halfW: HALF_W, halfH: HALF_H };
}
/** 等距绘制深度(连续值,移动插值用;与 compareIsoDrawOrder 配套) */
export function isoDrawDepthFromWorld(world: Vec3): { x: number; y: number } {
const cx = (world.y / HALF_H + world.x / HALF_W) * 0.5;
const cy = (world.y / HALF_H - world.x / HALF_W) * 0.5;
return { x: cx, y: cy };
}