feat(player): 优化角色移动方向更新机制
改进了角色在寻路移动过程中的方向判断算法,通过聚合未来路径节点的方向信息来减少转向突变,提升移动动画的流畅性。同时调整了碰撞体参数和场景布局以优化游戏体验。
This commit is contained in:
@@ -332,8 +332,8 @@
|
|||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
"_lpos": {
|
"_lpos": {
|
||||||
"__type__": "cc.Vec3",
|
"__type__": "cc.Vec3",
|
||||||
"x": -44.282,
|
"x": -51.831,
|
||||||
"y": -755.631,
|
"y": -759.406,
|
||||||
"z": 0
|
"z": 0
|
||||||
},
|
},
|
||||||
"_lrot": {
|
"_lrot": {
|
||||||
@@ -602,7 +602,7 @@
|
|||||||
"a": 255
|
"a": 255
|
||||||
},
|
},
|
||||||
"_spriteFrame": {
|
"_spriteFrame": {
|
||||||
"__uuid__": "1c7b5663-daeb-4a52-970f-2c530866798f@f9941",
|
"__uuid__": "9ff0a243-0244-4517-9cd3-b95fd18ce759@f9941",
|
||||||
"__expectedType__": "cc.SpriteFrame"
|
"__expectedType__": "cc.SpriteFrame"
|
||||||
},
|
},
|
||||||
"_type": 0,
|
"_type": 0,
|
||||||
@@ -1468,13 +1468,13 @@
|
|||||||
"_restitution": 0,
|
"_restitution": 0,
|
||||||
"_offset": {
|
"_offset": {
|
||||||
"__type__": "cc.Vec2",
|
"__type__": "cc.Vec2",
|
||||||
"x": 0.5,
|
"x": -0.1,
|
||||||
"y": 5
|
"y": 5
|
||||||
},
|
},
|
||||||
"_size": {
|
"_size": {
|
||||||
"__type__": "cc.Size",
|
"__type__": "cc.Size",
|
||||||
"width": 61.4,
|
"width": 55.1,
|
||||||
"height": 129.1
|
"height": 114
|
||||||
},
|
},
|
||||||
"_id": "634GiEUhBB8Z1aGzkT6Zyd"
|
"_id": "634GiEUhBB8Z1aGzkT6Zyd"
|
||||||
},
|
},
|
||||||
@@ -3591,13 +3591,13 @@
|
|||||||
"_restitution": 0,
|
"_restitution": 0,
|
||||||
"_offset": {
|
"_offset": {
|
||||||
"__type__": "cc.Vec2",
|
"__type__": "cc.Vec2",
|
||||||
"x": 6.4,
|
"x": 1.7,
|
||||||
"y": 3.7
|
"y": -1.2
|
||||||
},
|
},
|
||||||
"_size": {
|
"_size": {
|
||||||
"__type__": "cc.Size",
|
"__type__": "cc.Size",
|
||||||
"width": 108,
|
"width": 101,
|
||||||
"height": 175
|
"height": 147.1
|
||||||
},
|
},
|
||||||
"_id": "cdIXFZyqRL66Jq6KOCWAZ6"
|
"_id": "cdIXFZyqRL66Jq6KOCWAZ6"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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';
|
import { TiledMapPathfinder } from './TiledMapPathfinder';
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@@ -63,6 +63,10 @@ export class PlayerController extends Component {
|
|||||||
// 道具列表
|
// 道具列表
|
||||||
private props: Node[] = [];
|
private props: Node[] = [];
|
||||||
|
|
||||||
|
// 行走方向相关参数
|
||||||
|
private readonly directionLookAheadSteps = 2; // 更新方向时向前查看的路径节点数
|
||||||
|
private readonly minDirectionUpdateDistance = 1; // 小于该距离时不刷新方向,避免抖动
|
||||||
|
|
||||||
private guideNode: Node | null = null;
|
private guideNode: Node | null = null;
|
||||||
private activePopup: Node | null = null;
|
private activePopup: Node | null = null;
|
||||||
private activePopupName: string | null = null;
|
private activePopupName: string | null = null;
|
||||||
@@ -422,8 +426,8 @@ export class PlayerController extends Component {
|
|||||||
deltaY: number,
|
deltaY: number,
|
||||||
overrides?: { horizontal?: 'Left' | 'Right', vertical?: 'Up' | 'Down' }
|
overrides?: { horizontal?: 'Left' | 'Right', vertical?: 'Up' | 'Down' }
|
||||||
): PlayerDirection {
|
): PlayerDirection {
|
||||||
const horizontalThreshold = 0.5;
|
const horizontalThreshold = 0.1;
|
||||||
const verticalThreshold = 0.5;
|
const verticalThreshold = 0.1;
|
||||||
|
|
||||||
let horizontal: 'Left' | 'Right' = overrides?.horizontal ?? (this.isFacingLeft() ? 'Left' : 'Right');
|
let horizontal: 'Left' | 'Right' = overrides?.horizontal ?? (this.isFacingLeft() ? 'Left' : 'Right');
|
||||||
if (!overrides?.horizontal && Math.abs(deltaX) > horizontalThreshold) {
|
if (!overrides?.horizontal && Math.abs(deltaX) > horizontalThreshold) {
|
||||||
@@ -696,32 +700,51 @@ export class PlayerController extends Component {
|
|||||||
|
|
||||||
// 计算当前在路径中的大致位置
|
// 计算当前在路径中的大致位置
|
||||||
const pathLength = this.currentPath.length;
|
const pathLength = this.currentPath.length;
|
||||||
const currentPathIndex = Math.floor(ratio * (pathLength - 1));
|
const approxIndex = Math.floor(ratio * (pathLength - 1));
|
||||||
|
if (approxIndex >= pathLength - 1) {
|
||||||
// 确保不超出路径范围
|
|
||||||
const nextIndex = Math.min(currentPathIndex + 1, pathLength - 1);
|
|
||||||
|
|
||||||
// 如果已经到达最后一个路径点,不再更新方向
|
|
||||||
if (currentPathIndex >= pathLength - 1) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取当前路径点和下一个路径点
|
const currentPathIndex = Math.max(0, approxIndex);
|
||||||
const currentPathPoint = this.currentPath[currentPathIndex];
|
const nextIndex = currentPathIndex + 1;
|
||||||
const nextPathPoint = this.currentPath[nextIndex];
|
const maxIndex = Math.min(pathLength - 1, nextIndex + this.directionLookAheadSteps);
|
||||||
|
|
||||||
// 计算到下一个路径点的方向
|
let weightedDirX = 0;
|
||||||
const deltaX = nextPathPoint.x - currentPos.x;
|
let weightedDirY = 0;
|
||||||
const deltaY = nextPathPoint.y - currentPos.y;
|
let totalWeight = 0;
|
||||||
|
let farthestDistance = 0;
|
||||||
|
|
||||||
// 如果移动距离很小,不更新动画
|
// 聚合未来若干路径节点的方向信息,减缓转向突变
|
||||||
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
for (let i = nextIndex; i <= maxIndex; i++) {
|
||||||
if (distance < 1) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算新的方向
|
// 计算新的方向
|
||||||
const newDirection = this.resolveDirectionFromDelta(deltaX, deltaY);
|
const newDirection = this.resolveDirectionFromDelta(averagedDirX, averagedDirY);
|
||||||
|
|
||||||
// 只有当方向发生显著变化时才更新
|
// 只有当方向发生显著变化时才更新
|
||||||
if (newDirection !== this.currentDirection) {
|
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