feat(player): 优化角色移动方向更新机制
改进了角色在寻路移动过程中的方向判断算法,通过聚合未来路径节点的方向信息来减少转向突变,提升移动动画的流畅性。同时调整了碰撞体参数和场景布局以优化游戏体验。
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { _decorator, Component, Node, Vec3, input, Input, EventTouch, Camera, view, tween, Animation, Collider2D, BoxCollider2D, Contact2DType, Label, Color, Canvas, UITransform, AudioSource, director } from 'cc';
|
||||
import { _decorator, Component, Node, Vec3, input, Input, EventTouch, Camera, view, tween, Animation, Collider2D, BoxCollider2D, Contact2DType, Label, Color, Canvas, UITransform, AudioSource, director, PhysicsSystem2D, EPhysics2DDrawFlags } from 'cc';
|
||||
import { TiledMapPathfinder } from './TiledMapPathfinder';
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@@ -63,6 +63,10 @@ export class PlayerController extends Component {
|
||||
// 道具列表
|
||||
private props: Node[] = [];
|
||||
|
||||
// 行走方向相关参数
|
||||
private readonly directionLookAheadSteps = 2; // 更新方向时向前查看的路径节点数
|
||||
private readonly minDirectionUpdateDistance = 1; // 小于该距离时不刷新方向,避免抖动
|
||||
|
||||
private guideNode: Node | null = null;
|
||||
private activePopup: Node | null = null;
|
||||
private activePopupName: string | null = null;
|
||||
@@ -422,8 +426,8 @@ export class PlayerController extends Component {
|
||||
deltaY: number,
|
||||
overrides?: { horizontal?: 'Left' | 'Right', vertical?: 'Up' | 'Down' }
|
||||
): PlayerDirection {
|
||||
const horizontalThreshold = 0.5;
|
||||
const verticalThreshold = 0.5;
|
||||
const horizontalThreshold = 0.1;
|
||||
const verticalThreshold = 0.1;
|
||||
|
||||
let horizontal: 'Left' | 'Right' = overrides?.horizontal ?? (this.isFacingLeft() ? 'Left' : 'Right');
|
||||
if (!overrides?.horizontal && Math.abs(deltaX) > horizontalThreshold) {
|
||||
@@ -696,32 +700,51 @@ export class PlayerController extends Component {
|
||||
|
||||
// 计算当前在路径中的大致位置
|
||||
const pathLength = this.currentPath.length;
|
||||
const currentPathIndex = Math.floor(ratio * (pathLength - 1));
|
||||
|
||||
// 确保不超出路径范围
|
||||
const nextIndex = Math.min(currentPathIndex + 1, pathLength - 1);
|
||||
|
||||
// 如果已经到达最后一个路径点,不再更新方向
|
||||
if (currentPathIndex >= pathLength - 1) {
|
||||
const approxIndex = Math.floor(ratio * (pathLength - 1));
|
||||
if (approxIndex >= pathLength - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取当前路径点和下一个路径点
|
||||
const currentPathPoint = this.currentPath[currentPathIndex];
|
||||
const nextPathPoint = this.currentPath[nextIndex];
|
||||
const currentPathIndex = Math.max(0, approxIndex);
|
||||
const nextIndex = currentPathIndex + 1;
|
||||
const maxIndex = Math.min(pathLength - 1, nextIndex + this.directionLookAheadSteps);
|
||||
|
||||
// 计算到下一个路径点的方向
|
||||
const deltaX = nextPathPoint.x - currentPos.x;
|
||||
const deltaY = nextPathPoint.y - currentPos.y;
|
||||
let weightedDirX = 0;
|
||||
let weightedDirY = 0;
|
||||
let totalWeight = 0;
|
||||
let farthestDistance = 0;
|
||||
|
||||
// 如果移动距离很小,不更新动画
|
||||
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||
if (distance < 1) {
|
||||
// 聚合未来若干路径节点的方向信息,减缓转向突变
|
||||
for (let i = nextIndex; i <= maxIndex; i++) {
|
||||
const samplePoint = this.currentPath[i];
|
||||
const deltaX = samplePoint.x - currentPos.x;
|
||||
const deltaY = samplePoint.y - currentPos.y;
|
||||
const distanceToPoint = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||
|
||||
farthestDistance = Math.max(farthestDistance, distanceToPoint);
|
||||
if (distanceToPoint < 0.0001) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const weight = i - currentPathIndex;
|
||||
weightedDirX += (deltaX / distanceToPoint) * weight;
|
||||
weightedDirY += (deltaY / distanceToPoint) * weight;
|
||||
totalWeight += weight;
|
||||
}
|
||||
|
||||
if (totalWeight === 0 || farthestDistance < this.minDirectionUpdateDistance) {
|
||||
return;
|
||||
}
|
||||
|
||||
const averagedDirX = weightedDirX / totalWeight;
|
||||
const averagedDirY = weightedDirY / totalWeight;
|
||||
const averagedMagnitude = Math.sqrt(averagedDirX * averagedDirX + averagedDirY * averagedDirY);
|
||||
if (averagedMagnitude < 0.1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 计算新的方向
|
||||
const newDirection = this.resolveDirectionFromDelta(deltaX, deltaY);
|
||||
const newDirection = this.resolveDirectionFromDelta(averagedDirX, averagedDirY);
|
||||
|
||||
// 只有当方向发生显著变化时才更新
|
||||
if (newDirection !== this.currentDirection) {
|
||||
@@ -1346,23 +1369,6 @@ export class PlayerController extends Component {
|
||||
}
|
||||
|
||||
|
||||
private setNodeWorldPosition(node: Node, worldPos: Vec3) {
|
||||
const parent = node.parent;
|
||||
if (!parent) {
|
||||
node.setWorldPosition(worldPos);
|
||||
return;
|
||||
}
|
||||
|
||||
const parentTransform = parent.getComponent(UITransform);
|
||||
if (parentTransform) {
|
||||
const localResult = parentTransform.convertToNodeSpaceAR(new Vec3(worldPos.x, worldPos.y, worldPos.z));
|
||||
node.setPosition(localResult);
|
||||
return;
|
||||
}
|
||||
|
||||
node.setWorldPosition(worldPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* 播放生命值标签强调动画(成功时)
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user