157 lines
4.3 KiB
TypeScript
157 lines
4.3 KiB
TypeScript
import { Node, Vec3, Tween, tween } from 'cc';
|
|
import { Position } from '../../Shared/protocols/base';
|
|
import { RoleController } from '../../CC/RoleController';
|
|
|
|
/**
|
|
* RemotePlayer 远程玩家
|
|
* 负责管理远程玩家的显示和位置同步
|
|
*/
|
|
export class RemotePlayer {
|
|
/** 玩家节点 */
|
|
private playerNode: Node = null;
|
|
|
|
/** 玩家ID */
|
|
private playerId: string = '';
|
|
|
|
/** 玩家名称 */
|
|
private playerName: string = '';
|
|
|
|
/** 当前位置 */
|
|
private currentPosition: Vec3 = new Vec3();
|
|
|
|
/** 目标位置 */
|
|
private targetPosition: Vec3 = new Vec3();
|
|
|
|
/** 角色控制器(控制动画) */
|
|
private roleController: RoleController = null;
|
|
|
|
/** 移动补间 */
|
|
private moveTween: Tween<Node> = null;
|
|
|
|
/** 是否正在移动 */
|
|
private isMoving: boolean = false;
|
|
|
|
/**
|
|
* 初始化远程玩家
|
|
*/
|
|
public init(playerNode: Node, playerId: string, playerName: string, position: Position): void {
|
|
this.playerNode = playerNode;
|
|
this.playerId = playerId;
|
|
this.playerName = playerName;
|
|
this.currentPosition.set(position.x, 0, position.y);
|
|
this.targetPosition.set(position.x, 0, position.y);
|
|
|
|
// 获取 RoleController 组件
|
|
this.roleController = this.playerNode.getComponentInChildren(RoleController);
|
|
if (!this.roleController) {
|
|
console.warn('[RemotePlayer] 未找到 RoleController 组件');
|
|
} else {
|
|
// 初始播放待机动画
|
|
this.roleController.PlayAnimation('idle', true);
|
|
}
|
|
|
|
console.log('[RemotePlayer] 初始化完成:', playerName);
|
|
}
|
|
|
|
/**
|
|
* 更新位置
|
|
* 收到服务器广播的移动消息时调用
|
|
*/
|
|
public updatePosition(position: Position): void {
|
|
this.targetPosition.set(position.x, 0, position.y);
|
|
|
|
// 计算移动方向和距离
|
|
const direction = this.targetPosition.clone().subtract(this.currentPosition);
|
|
const distance = direction.length();
|
|
|
|
// 如果距离太小,不做处理
|
|
if (distance < 0.1) {
|
|
return;
|
|
}
|
|
|
|
// 停止之前的移动补间
|
|
if (this.moveTween) {
|
|
this.moveTween.stop();
|
|
this.moveTween = null;
|
|
}
|
|
|
|
// 计算朝向
|
|
if (distance > 0.01) {
|
|
const targetAngle = Math.atan2(direction.x, -direction.z) * (180 / Math.PI);
|
|
this.playerNode.setRotationFromEuler(0, targetAngle, 0);
|
|
}
|
|
|
|
// 播放移动动画
|
|
if (!this.isMoving) {
|
|
this.isMoving = true;
|
|
if (this.roleController) {
|
|
this.roleController.PlayAnimation('move', true);
|
|
}
|
|
}
|
|
|
|
// 计算移动时间(根据距离,假设速度为5单位/秒)
|
|
const moveSpeed = 5;
|
|
const moveDuration = distance / moveSpeed;
|
|
|
|
// 创建移动补间
|
|
this.moveTween = tween(this.playerNode)
|
|
.to(moveDuration, { position: this.targetPosition }, {
|
|
onUpdate: (target, ratio) => {
|
|
// 更新当前位置
|
|
this.currentPosition.set(this.playerNode.position);
|
|
},
|
|
onComplete: () => {
|
|
// 移动完成,播放待机动画
|
|
this.isMoving = false;
|
|
if (this.roleController) {
|
|
this.roleController.PlayAnimation('idle', true);
|
|
}
|
|
this.moveTween = null;
|
|
}
|
|
})
|
|
.start();
|
|
}
|
|
|
|
/**
|
|
* 获取玩家ID
|
|
*/
|
|
public getPlayerId(): string {
|
|
return this.playerId;
|
|
}
|
|
|
|
/**
|
|
* 获取玩家名称
|
|
*/
|
|
public getPlayerName(): string {
|
|
return this.playerName;
|
|
}
|
|
|
|
/**
|
|
* 获取玩家节点
|
|
*/
|
|
public getPlayerNode(): Node {
|
|
return this.playerNode;
|
|
}
|
|
|
|
/**
|
|
* 销毁远程玩家
|
|
*/
|
|
public destroy(): void {
|
|
// 停止移动补间
|
|
if (this.moveTween) {
|
|
this.moveTween.stop();
|
|
this.moveTween = null;
|
|
}
|
|
|
|
// 销毁节点
|
|
if (this.playerNode) {
|
|
this.playerNode.destroy();
|
|
this.playerNode = null;
|
|
}
|
|
|
|
this.roleController = null;
|
|
|
|
console.log('[RemotePlayer] 已销毁:', this.playerName);
|
|
}
|
|
}
|