import { instantiate, Node, Prefab } from 'cc'; import { NetManager } from '../../Framework/Net/NetManager'; import { ResMgr } from '../../Framework/ResMgr/ResMgr'; import { UIMgr } from '../../Framework/UI/UIMgr'; import { MsgPlayerJoin } from '../../Shared/protocols/MsgPlayerJoin'; import { MsgPlayerMove } from '../../Shared/protocols/MsgPlayerMove'; import { PlayerInfo } from '../../Shared/protocols/MsgResLogin'; import { CameraController } from './CameraController'; import { PlayerController } from './PlayerController'; import { PlayerInfoData } from './PlayerInfo'; import { RemotePlayer } from './RemotePlayer'; import { UIGame } from './UIGame'; /** * World 世界管理器 * 负责管理游戏世界中的所有玩家 * 包括本地玩家和远程玩家的创建、更新和销毁 */ export class World { private static instance: World = null; /** 世界根节点 */ private worldRoot: Node = null; /** 本地玩家信息 */ private localPlayer: PlayerInfo = null; /** 本地玩家控制器 */ private localPlayerController: PlayerController = null; /** 本地玩家节点 */ private localPlayerNode: Node = null; /** 远程玩家列表 Map */ private remotePlayers: Map = new Map(); /** 玩家模型预制体 */ private playerPrefab: Prefab = null; /** 摄像机控制器 */ private cameraController: CameraController = null; /** UIGame实例 */ private uiGameInstance: UIGame = null; private constructor() { } public static getInstance(): World { if (!World.instance) { World.instance = new World(); } return World.instance; } /** * 初始化世界 * @param worldRoot 世界根节点 * @param localPlayer 本地玩家信息 * @param otherPlayers 其他在线玩家信息 */ public async init(worldRoot: Node, localPlayer: PlayerInfo, otherPlayers?: PlayerInfo[]): Promise { this.worldRoot = worldRoot; this.localPlayer = localPlayer; // 获取UIGame实例 this.uiGameInstance = UIMgr.getInstance().get(UIGame) as UIGame; // 加载玩家模型预制体 await this.loadPlayerPrefab(); // 注册网络消息监听 this.registerNetworkListeners(); // 创建本地玩家 await this.createLocalPlayer(); // 创建其他已在线的玩家 await this.createOtherPlayers(otherPlayers); console.log('[World] 世界初始化完成'); } /** * 加载玩家模型预制体 */ private async loadPlayerPrefab(): Promise { try { this.playerPrefab = await ResMgr.getInstance().load('res', 'Actor/M1/M1', Prefab); console.log('[World] 玩家模型预制体加载成功'); } catch (error) { console.error('[World] 加载玩家模型预制体失败:', error); } } /** * 注册网络消息监听 */ private registerNetworkListeners(): void { const netManager = NetManager.getInstance(); // 监听玩家加入消息 netManager.listenMsg('PlayerJoin', (msg: MsgPlayerJoin) => { this.onPlayerJoin(msg); }); // 监听玩家移动消息 netManager.listenMsg('PlayerMove', (msg: MsgPlayerMove) => { this.onPlayerMove(msg); }); console.log('[World] 网络消息监听注册完成'); } /** * 创建本地玩家 */ private async createLocalPlayer(): Promise { if (!this.playerPrefab) { console.error('[World] 玩家模型预制体未加载'); return; } const x = this.localPlayer.position.x / 1000 const y = this.localPlayer.position.y / 1000 // 实例化玩家节点 this.localPlayerNode = instantiate(this.playerPrefab); this.localPlayerNode.name = `Player_${this.localPlayer.id}_Local`; this.localPlayerNode.setPosition(x, y, 0); this.worldRoot.addChild(this.localPlayerNode); // 创建本地玩家控制器 this.localPlayerController = this.localPlayerNode.addComponent(PlayerController); this.localPlayerController.init(this.localPlayer); // 创建并绑定摄像机控制器(只有本地玩家需要) this.cameraController = this.worldRoot.addComponent(CameraController) as CameraController; this.cameraController.setTarget(this.localPlayerNode); console.log('[World] 本地玩家创建完成:', this.localPlayer.name); } /** * 创建其他已在线的玩家 */ private async createOtherPlayers(otherPlayers?: PlayerInfo[]): Promise { if (!otherPlayers || otherPlayers.length === 0) { console.log('[World] 无其他在线玩家'); return; } if (!this.playerPrefab) { console.error('[World] 玩家模型预制体未加载,无法创建其他玩家'); return; } console.log('[World] 开始创建其他在线玩家,数量:', otherPlayers.length); for (const playerInfo of otherPlayers) { // 跳过本地玩家(双重保险) if (playerInfo.id === this.localPlayer.id) { continue; } // 检查是否已存在 if (this.remotePlayers.has(playerInfo.id)) { console.warn('[World] 远程玩家已存在:', playerInfo.id); continue; } try { // 实例化玩家节点 const playerNode = instantiate(this.playerPrefab); playerNode.name = `Player_${playerInfo.id}_Remote`; const x = playerInfo.position.x / 1000; const y = playerInfo.position.y / 1000; playerNode.setPosition(x, y, 0); this.worldRoot.addChild(playerNode); // 创建远程玩家控制器 const remotePlayer = new RemotePlayer(); remotePlayer.init(playerNode, playerInfo.id, playerInfo.name, playerInfo.position); this.remotePlayers.set(playerInfo.id, remotePlayer); console.log('[World] 其他玩家创建完成:', playerInfo.name); } catch (error) { console.error('[World] 创建其他玩家失败:', playerInfo.name, error); } } } /** * 处理玩家加入消息 */ private onPlayerJoin(msg: MsgPlayerJoin): void { console.log('[World] 玩家加入:', msg.playerName); // 如果是本地玩家,不处理 if (msg.playerId === this.localPlayer.id) { return; } // 创建远程玩家 this.createRemotePlayer(msg); } /** * 创建远程玩家 */ private async createRemotePlayer(msg: MsgPlayerJoin): Promise { if (!this.playerPrefab) { console.error('[World] 玩家模型预制体未加载'); return; } // 检查是否已存在 if (this.remotePlayers.has(msg.playerId)) { console.warn('[World] 远程玩家已存在:', msg.playerId); return; } // 实例化玩家节点 const playerNode = instantiate(this.playerPrefab); playerNode.name = `Player_${msg.playerId}_Remote`; const x = msg.position.x / 1000 const y = msg.position.y / 1000 playerNode.setPosition(x, y, 0); this.worldRoot.addChild(playerNode); // 创建远程玩家控制器 const remotePlayer = new RemotePlayer(); remotePlayer.init(playerNode, msg.playerId, msg.playerName, msg.position); this.remotePlayers.set(msg.playerId, remotePlayer); console.log('[World] 远程玩家创建完成:', msg.playerName); } /** * 处理玩家移动消息 */ private onPlayerMove(msg: MsgPlayerMove): void { // 如果是本地玩家,不处理 if (msg.playerId === this.localPlayer.id) { return; } // 更新远程玩家位置 const remotePlayer = this.remotePlayers.get(msg.playerId); if (remotePlayer) { remotePlayer.updatePosition(msg.position); } } /** * 获取本地玩家控制器 */ public getLocalPlayerController(): PlayerController { return this.localPlayerController; } /** * 更新所有玩家信息显示 */ public updateAllPlayersInfo(): void { if (!this.uiGameInstance || !this.cameraController) { return; } const uinode = this.uiGameInstance.getNode() const playerDataList: PlayerInfoData[] = []; // 添加本地玩家信息 if (this.localPlayerNode && this.localPlayer) { // 直接使用节点的世界坐标 const worldPos = this.localPlayerNode.worldPosition; // 正确的坐标转换流程:世界坐标 -> 世界摄像机坐标 -> UI摄像机坐标 const uiScreenPos = this.cameraController.worldToUICamera(worldPos, uinode); playerDataList.push({ playerId: this.localPlayer.id, playerName: this.localPlayer.name, screenPosition: uiScreenPos, realPosition: worldPos // 使用世界坐标作为真实位置 }); } // 添加远程玩家信息 for (const [playerId, remotePlayer] of this.remotePlayers.entries()) { const remotePlayerNode = remotePlayer.getPlayerNode(); if (remotePlayerNode) { const worldPos = remotePlayerNode.worldPosition; // 正确的坐标转换流程:世界坐标 -> 世界摄像机坐标 -> UI摄像机坐标 const uiScreenPos = this.cameraController.worldToUICamera(worldPos, uinode); playerDataList.push({ playerId: playerId, playerName: remotePlayer.getPlayerName(), screenPosition: uiScreenPos, realPosition: worldPos // 使用世界坐标作为真实位置 }); } } // 更新UI显示 this.uiGameInstance.updatePlayerInfo(playerDataList); } /** * 在update中定期更新玩家信息显示 */ public update(deltaTime: number): void { // 每帧更新玩家信息显示 this.updateAllPlayersInfo(); } /** * 销毁世界 */ public destroy(): void { // 注意: TSRPC 的 listenMsg 不提供取消监听的方法 // 在实际使用中,监听会在连接断开时自动清除 // 销毁本地玩家 if (this.localPlayerNode) { this.localPlayerNode.destroy(); this.localPlayerNode = null; } this.localPlayerController = null; // 销毁摄像机控制器 if (this.cameraController) { this.cameraController.node.removeComponent(CameraController); this.cameraController = null; } // 销毁所有远程玩家 this.remotePlayers.forEach((remotePlayer) => { remotePlayer.destroy(); }); this.remotePlayers.clear(); // 释放资源 if (this.playerPrefab) { ResMgr.getInstance().release('resources', 'res://Actor/M1/M1'); this.playerPrefab = null; } this.worldRoot = null; this.localPlayer = null; console.log('[World] 世界已销毁'); } /** * 清理单例 */ public static clear(): void { if (World.instance) { World.instance.destroy(); World.instance = null; } } }