import { _decorator, Component, input, Input, EventTouch, Camera, Node, Vec3, UITransform, math } from 'cc'; const { ccclass, property } = _decorator; interface NodeCell { x: number; y: number; g: number; h: number; f: number; parent?: NodeCell; } @ccclass('GameController') export class GameController extends Component { @property(Camera) camera: Camera = null!; @property(Node) player: Node = null!; @property(Node) map: Node = null!; @property gridSize: number = 32; @property moveSpeed: number = 200; @property camSmooth: number = 5; private mapData: number[][] = [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 0, 0, 1, 1, 1, 0], [0, 0, 0, 1, 0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 1, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 0, 0, 0], ]; private path: Vec3[] = []; private camPos: Vec3 = new Vec3(); private mapSize: Vec3 = new Vec3(); onLoad() { input.on(Input.EventType.TOUCH_END, this.onTouchEnd, this); // 获取地图大小 const ui = this.map.getComponent(UITransform); if (ui) { this.mapSize.set(ui.width, ui.height, 0); } } onDestroy() { input.off(Input.EventType.TOUCH_END, this.onTouchEnd, this); } // 点击地图 -> 计算寻路路径 onTouchEnd(event: EventTouch) { if (!this.camera) return; const screenPos = event.getLocation(); const worldPos = this.camera.screenToWorld(new Vec3(screenPos.x, screenPos.y, 0)); const startCell = this.worldToCell(this.player.getWorldPosition()); const endCell = this.worldToCell(worldPos); const cellPath = this.findPath(startCell, endCell); if (cellPath.length > 0) { this.path = cellPath.map(c => this.cellToWorld(c)); } } update(deltaTime: number) { // === 角色移动 === if (this.path.length > 0) { const pos = this.player.getWorldPosition(); const target = this.path[0]; const dir = target.subtract(pos); const dist = dir.length(); if (dist < this.moveSpeed * deltaTime) { this.player.setWorldPosition(target); this.path.shift(); } else { dir.normalize(); const move = dir.multiplyScalar(this.moveSpeed * deltaTime); this.player.setWorldPosition(pos.add(move)); } } // === 相机跟随 === const targetPos = this.player.getWorldPosition(); const desiredPos = new Vec3(targetPos.x, targetPos.y, 1000); // Z 拉远 Vec3.lerp(this.camPos, this.camera.node.getWorldPosition(), desiredPos, deltaTime * this.camSmooth); // 限制相机范围 const halfW = this.mapSize.x / 2; const halfH = this.mapSize.y / 2; const viewW = 400; // 你可以用实际相机视口宽高 const viewH = 300; this.camPos.x = math.clamp(this.camPos.x, -halfW + viewW, halfW - viewW); this.camPos.y = math.clamp(this.camPos.y, -halfH + viewH, halfH - viewH); this.camera.node.setWorldPosition(this.camPos); } // ============ A* 寻路实现 ============ worldToCell(worldPos: Vec3): { x: number, y: number } { return { x: Math.floor(worldPos.x / this.gridSize), y: Math.floor(worldPos.y / this.gridSize), }; } cellToWorld(cell: { x: number, y: number }): Vec3 { return new Vec3( cell.x * this.gridSize + this.gridSize / 2, cell.y * this.gridSize + this.gridSize / 2, 0 ); } findPath(start: { x: number, y: number }, end: { x: number, y: number }): { x: number, y: number }[] { const open: NodeCell[] = []; const closed: boolean[][] = []; const rows = this.mapData.length; const cols = this.mapData[0].length; function heuristic(a: { x: number, y: number }, b: { x: number, y: number }) { return Math.abs(a.x - b.x) + Math.abs(a.y - b.y); } open.push({ x: start.x, y: start.y, g: 0, h: heuristic(start, end), f: 0 }); while (open.length > 0) { open.sort((a, b) => (a.g + a.h) - (b.g + b.h)); const current = open.shift()!; closed[current.y] = closed[current.y] || []; closed[current.y][current.x] = true; if (current.x === end.x && current.y === end.y) { const path: { x: number, y: number }[] = []; let node: NodeCell | undefined = current; while (node) { path.unshift({ x: node.x, y: node.y }); node = node.parent; } return path; } const neighbors = [ { x: current.x + 1, y: current.y }, { x: current.x - 1, y: current.y }, { x: current.x, y: current.y + 1 }, { x: current.x, y: current.y - 1 }, ]; for (const n of neighbors) { if (n.x < 0 || n.y < 0 || n.y >= rows || n.x >= cols) continue; if (this.mapData[n.y][n.x] === 1) continue; if (closed[n.y]?.[n.x]) continue; const g = current.g + 1; const h = heuristic(n, end); const existing = open.find(o => o.x === n.x && o.y === n.y); if (!existing || g < existing.g) { open.push({ x: n.x, y: n.y, g, h, f: g + h, parent: current }); } } } return []; } }