Files
rougelike-demo/client/assets/scripts/App/Game/World.ts
2025-12-14 23:35:08 +08:00

229 lines
6.6 KiB
TypeScript

import { Node, Vec3, instantiate, Prefab } from 'cc';
import { NetManager } from '../../Framework/Net/NetManager';
import { ResMgr } from '../../Framework/ResMgr/ResMgr';
import { MsgPlayerJoin } from '../../Shared/protocols/MsgPlayerJoin';
import { MsgPlayerMove } from '../../Shared/protocols/MsgPlayerMove';
import { PlayerInfo } from '../../Shared/protocols/PtlLogin';
import { PlayerController } from './PlayerController';
import { RemotePlayer } from './RemotePlayer';
/**
* 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<playerId, RemotePlayer> */
private remotePlayers: Map<string, RemotePlayer> = new Map();
/** 玩家模型预制体 */
private playerPrefab: Prefab = null;
private constructor() {}
public static getInstance(): World {
if (!World.instance) {
World.instance = new World();
}
return World.instance;
}
/**
* 初始化世界
* @param worldRoot 世界根节点
* @param localPlayer 本地玩家信息
*/
public async init(worldRoot: Node, localPlayer: PlayerInfo): Promise<void> {
this.worldRoot = worldRoot;
this.localPlayer = localPlayer;
// 加载玩家模型预制体
await this.loadPlayerPrefab();
// 注册网络消息监听
this.registerNetworkListeners();
// 创建本地玩家
await this.createLocalPlayer();
console.log('[World] 世界初始化完成');
}
/**
* 加载玩家模型预制体
*/
private async loadPlayerPrefab(): Promise<void> {
try {
this.playerPrefab = await ResMgr.getInstance().load('resources', '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<void> {
if (!this.playerPrefab) {
console.error('[World] 玩家模型预制体未加载');
return;
}
// 实例化玩家节点
this.localPlayerNode = instantiate(this.playerPrefab);
this.localPlayerNode.name = `Player_${this.localPlayer.id}_Local`;
this.localPlayerNode.setPosition(this.localPlayer.position.x, 0, this.localPlayer.position.y);
this.worldRoot.addChild(this.localPlayerNode);
// 创建本地玩家控制器
this.localPlayerController = this.localPlayerNode.addComponent(PlayerController);
this.localPlayerController.init(this.localPlayer);
console.log('[World] 本地玩家创建完成:', this.localPlayer.name);
}
/**
* 处理玩家加入消息
*/
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<void> {
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`;
playerNode.setPosition(msg.position.x, 0, msg.position.y);
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 destroy(): void {
// 注意: TSRPC 的 listenMsg 不提供取消监听的方法
// 在实际使用中,监听会在连接断开时自动清除
// 销毁本地玩家
if (this.localPlayerNode) {
this.localPlayerNode.destroy();
this.localPlayerNode = null;
}
this.localPlayerController = 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;
}
}
}