feat: 支持自动寻路算法
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { _decorator, Component, Node, Vec3, input, Input, EventTouch, Camera, view } from 'cc';
|
||||
import { _decorator, Component, Node, Vec3, input, Input, EventTouch, Camera, view, tween } from 'cc';
|
||||
import { TiledMapPathfinder } from './TiledMapPathfinder';
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('PlayerController')
|
||||
@@ -10,8 +11,11 @@ export class PlayerController extends Component {
|
||||
@property(Camera)
|
||||
camera: Camera | null = null; // 主摄像机
|
||||
|
||||
@property({ range: [1, 20] })
|
||||
moveSpeed: number = 5; // 移动速度
|
||||
@property(TiledMapPathfinder)
|
||||
pathfinder: TiledMapPathfinder | null = null; // 寻路组件
|
||||
|
||||
@property({ range: [1, 300] })
|
||||
moveSpeed: number = 300; // 移动速度(像素/秒)
|
||||
|
||||
@property
|
||||
mapWidth: number = 1080; // 地图宽度
|
||||
@@ -20,7 +24,8 @@ export class PlayerController extends Component {
|
||||
mapHeight: number = 2560; // 地图高度
|
||||
|
||||
private isMoving: boolean = false;
|
||||
private targetPosition: Vec3 = new Vec3();
|
||||
private currentPath: Vec3[] = [];
|
||||
private currentPathIndex: number = 0;
|
||||
private originalPosition: Vec3 = new Vec3();
|
||||
|
||||
onLoad() {
|
||||
@@ -40,7 +45,7 @@ export class PlayerController extends Component {
|
||||
}
|
||||
|
||||
private onTouchStart(event: EventTouch) {
|
||||
if (!this.player || !this.camera) return;
|
||||
if (!this.player || !this.camera || !this.pathfinder) return;
|
||||
|
||||
// 获取触摸点的UI坐标
|
||||
const touchLocation = event.getUILocation();
|
||||
@@ -51,7 +56,7 @@ export class PlayerController extends Component {
|
||||
console.log(`触摸UI坐标: (${touchLocation.x}, ${touchLocation.y})`);
|
||||
console.log(`转换后世界坐标: (${worldPos.x.toFixed(2)}, ${worldPos.y.toFixed(2)})`);
|
||||
|
||||
this.moveToPosition(worldPos);
|
||||
this.moveToPositionWithPathfinding(worldPos);
|
||||
}
|
||||
|
||||
private screenToWorldPoint(screenPos: { x: number, y: number }): Vec3 {
|
||||
@@ -82,17 +87,41 @@ export class PlayerController extends Component {
|
||||
}
|
||||
|
||||
|
||||
private moveToPosition(worldPos: Vec3) {
|
||||
if (!this.player) return;
|
||||
private moveToPositionWithPathfinding(worldPos: Vec3) {
|
||||
if (!this.player || !this.pathfinder) return;
|
||||
|
||||
// 停止当前移动
|
||||
this.stopMovement();
|
||||
|
||||
// 限制目标位置在地图边界内
|
||||
const clampedPos = this.clampPlayerPosition(worldPos);
|
||||
|
||||
// 设置目标位置(保持Z轴不变)
|
||||
this.targetPosition.set(clampedPos.x, clampedPos.y, this.player.position.z);
|
||||
this.isMoving = true;
|
||||
// 检查目标位置是否可行走
|
||||
if (!this.pathfinder.isWorldPositionWalkable(clampedPos)) {
|
||||
console.log('目标位置不可行走,寻找最近的可行走位置');
|
||||
const closestWalkable = this.pathfinder.getClosestWalkablePosition(clampedPos);
|
||||
if (!closestWalkable) {
|
||||
console.warn('找不到可行走的位置');
|
||||
return;
|
||||
}
|
||||
clampedPos.set(closestWalkable);
|
||||
}
|
||||
|
||||
console.log(`移动目标: (${clampedPos.x.toFixed(2)}, ${clampedPos.y.toFixed(2)})`);
|
||||
// 使用寻路算法计算路径
|
||||
const startPos = this.player.position;
|
||||
this.currentPath = this.pathfinder.findPath(startPos, clampedPos);
|
||||
|
||||
if (this.currentPath.length === 0) {
|
||||
console.warn('无法找到路径');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`找到路径,包含${this.currentPath.length}个点`);
|
||||
|
||||
// 开始沿路径移动
|
||||
this.currentPathIndex = 0;
|
||||
this.isMoving = true;
|
||||
this.moveToNextWaypoint();
|
||||
}
|
||||
|
||||
// 限制玩家位置在地图边界内
|
||||
@@ -109,41 +138,50 @@ export class PlayerController extends Component {
|
||||
return clampedPosition;
|
||||
}
|
||||
|
||||
update(deltaTime: number) {
|
||||
if (!this.isMoving || !this.player) return;
|
||||
|
||||
const currentPos = this.player.position;
|
||||
const distance = Vec3.distance(currentPos, this.targetPosition);
|
||||
|
||||
// 如果距离很小,直接到达目标位置
|
||||
if (distance < 0.1) {
|
||||
this.player.position = this.targetPosition.clone();
|
||||
/**
|
||||
* 移动到路径中的下一个路径点
|
||||
*/
|
||||
private moveToNextWaypoint() {
|
||||
if (!this.player || this.currentPath.length === 0 || this.currentPathIndex >= this.currentPath.length) {
|
||||
this.isMoving = false;
|
||||
console.log('到达目标位置');
|
||||
console.log('路径移动完成');
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算移动方向
|
||||
const direction = new Vec3();
|
||||
Vec3.subtract(direction, this.targetPosition, currentPos);
|
||||
direction.normalize();
|
||||
const targetPos = this.currentPath[this.currentPathIndex];
|
||||
const currentPos = this.player.position;
|
||||
|
||||
// 计算这一帧应该移动的距离
|
||||
const moveDistance = this.moveSpeed * deltaTime * 100; // 增加移动速度倍数
|
||||
// 计算移动距离和时间
|
||||
const distance = Vec3.distance(currentPos, targetPos);
|
||||
const moveTime = distance / this.moveSpeed;
|
||||
|
||||
// 如果剩余距离小于这一帧要移动的距离,直接到达目标
|
||||
if (distance <= moveDistance) {
|
||||
this.player.position = this.targetPosition.clone();
|
||||
this.isMoving = false;
|
||||
console.log('到达目标位置');
|
||||
} else {
|
||||
// 正常移动
|
||||
const newPosition = new Vec3();
|
||||
Vec3.scaleAndAdd(newPosition, currentPos, direction, moveDistance);
|
||||
console.log(`移动到路径点${this.currentPathIndex}: (${targetPos.x.toFixed(2)}, ${targetPos.y.toFixed(2)})`);
|
||||
|
||||
// 确保新位置在地图边界内
|
||||
const clampedNewPosition = this.clampPlayerPosition(newPosition);
|
||||
this.player.position = clampedNewPosition;
|
||||
// 使用缓动移动到目标位置
|
||||
tween(this.player)
|
||||
.to(moveTime, { position: targetPos }, {
|
||||
onComplete: () => {
|
||||
this.currentPathIndex++;
|
||||
this.moveToNextWaypoint();
|
||||
}
|
||||
})
|
||||
.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止当前移动
|
||||
*/
|
||||
private stopMovement() {
|
||||
if (this.player) {
|
||||
tween(this.player).stop();
|
||||
}
|
||||
this.isMoving = false;
|
||||
this.currentPath = [];
|
||||
this.currentPathIndex = 0;
|
||||
}
|
||||
|
||||
update(deltaTime: number) {
|
||||
// 更新逻辑现在主要由缓动系统处理
|
||||
// 这里可以添加其他需要每帧更新的逻辑
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user