import { _decorator, Component, Node, Vec3, Camera, view } from 'cc'; const { ccclass, property } = _decorator; @ccclass('CameraFollow') export class CameraFollow extends Component { @property(Node) target: Node | null = null; // 要跟随的目标(玩家) @property({ range: [0.1, 10] }) followSpeed: number = 5.0; // 跟随速度 @property(Vec3) offset: Vec3 = new Vec3(0, 0, 10); // 相机相对目标的偏移 @property({ range: [0, 1] }) smoothness: number = 0.1; // 平滑度,0为瞬间跟随,1为最慢跟随 @property mapWidth: number = 1080; // 地图宽度 @property mapHeight: number = 2560; // 地图高度 private camera: Camera | null = null; onLoad() { // 获取相机组件 this.camera = this.getComponent(Camera); if (!this.camera) { console.error('CameraFollow: 未找到Camera组件'); } } start() { if (this.target) { // 初始化相机位置 const initialPos = this.target.position.clone(); initialPos.add(this.offset); this.node.position = initialPos; } } update(deltaTime: number) { if (!this.target) return; // 计算目标位置 const targetPosition = this.target.position.clone(); targetPosition.add(this.offset); // 应用地图边界限制 const clampedPosition = this.clampCameraPosition(targetPosition); // 使用插值实现平滑跟随 const currentPosition = this.node.position; const newPosition = new Vec3(); // 根据平滑度设置插值速度 const lerpFactor = Math.min(1.0, this.followSpeed * deltaTime * (1 - this.smoothness + 0.1)); Vec3.lerp(newPosition, currentPosition, clampedPosition, lerpFactor); this.node.position = newPosition; } // 限制相机位置在地图边界内 private clampCameraPosition(position: Vec3): Vec3 { if (!this.camera) return position; // 获取屏幕可见区域大小 const visibleSize = view.getVisibleSize(); // 计算相机能看到的世界区域的一半 const halfCameraWidth = visibleSize.width * 0.5; const halfCameraHeight = visibleSize.height * 0.5; // 计算地图边界(地图锚点为0.5,0.5,所以范围是-mapWidth/2到+mapWidth/2) const mapHalfWidth = this.mapWidth * 0.5; const mapHalfHeight = this.mapHeight * 0.5; // 计算相机位置的边界(确保相机边缘不超出地图边界) const minX = -mapHalfWidth + halfCameraWidth; const maxX = mapHalfWidth - halfCameraWidth; const minY = -mapHalfHeight + halfCameraHeight; const maxY = mapHalfHeight - halfCameraHeight; // 限制相机位置 const clampedPosition = position.clone(); clampedPosition.x = Math.max(minX, Math.min(maxX, position.x)); clampedPosition.y = Math.max(minY, Math.min(maxY, position.y)); return clampedPosition; } // 设置跟随目标 setTarget(target: Node) { this.target = target; if (target) { const initialPos = target.position.clone(); initialPos.add(this.offset); this.node.position = initialPos; } } // 设置偏移量 setOffset(offset: Vec3) { this.offset = offset; } // 瞬间移动到目标位置 snapToTarget() { if (!this.target) return; const targetPosition = this.target.position.clone(); targetPosition.add(this.offset); const clampedPosition = this.clampCameraPosition(targetPosition); this.node.position = clampedPosition; } }