feat(player): 优化角色移动方向更新机制

改进了角色在寻路移动过程中的方向判断算法,通过聚合未来路径节点的方向信息来减少转向突变,提升移动动画的流畅性。同时调整了碰撞体参数和场景布局以优化游戏体验。
This commit is contained in:
richarjiang
2025-10-21 09:49:40 +08:00
parent f70bf7ba14
commit a8dff683cc
2 changed files with 53 additions and 47 deletions

View File

@@ -332,8 +332,8 @@
"_prefab": null,
"_lpos": {
"__type__": "cc.Vec3",
"x": -44.282,
"y": -755.631,
"x": -51.831,
"y": -759.406,
"z": 0
},
"_lrot": {
@@ -602,7 +602,7 @@
"a": 255
},
"_spriteFrame": {
"__uuid__": "1c7b5663-daeb-4a52-970f-2c530866798f@f9941",
"__uuid__": "9ff0a243-0244-4517-9cd3-b95fd18ce759@f9941",
"__expectedType__": "cc.SpriteFrame"
},
"_type": 0,
@@ -1468,13 +1468,13 @@
"_restitution": 0,
"_offset": {
"__type__": "cc.Vec2",
"x": 0.5,
"x": -0.1,
"y": 5
},
"_size": {
"__type__": "cc.Size",
"width": 61.4,
"height": 129.1
"width": 55.1,
"height": 114
},
"_id": "634GiEUhBB8Z1aGzkT6Zyd"
},
@@ -3591,13 +3591,13 @@
"_restitution": 0,
"_offset": {
"__type__": "cc.Vec2",
"x": 6.4,
"y": 3.7
"x": 1.7,
"y": -1.2
},
"_size": {
"__type__": "cc.Size",
"width": 108,
"height": 175
"width": 101,
"height": 147.1
},
"_id": "cdIXFZyqRL66Jq6KOCWAZ6"
},

View File

@@ -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);
}
/**
* 播放生命值标签强调动画(成功时)
*/