219 lines
6.8 KiB
TypeScript
Raw Normal View History

2022-12-08 21:14:02 +08:00
import { _decorator, Component, Node, Prefab, instantiate, SpriteFrame, director } from "cc";
import { ActorManager } from "../Entity/Actor/ActorManager";
import DataManager from "../Global/DataManager";
import { JoyStickManager } from "../UI/JoyStickManager";
import { ResourceManager } from "../Global/ResourceManager";
import { EventEnum, PrefabPathEnum, SceneEnum, TexturePathEnum } from "../Enum";
import NetworkManager from "../Global/NetworkManager";
import ObjectPoolManager from "../Global/ObjectPoolManager";
import { BulletManager } from "../Entity/Bullet/BulletManager";
import { ApiMsgEnum, EntityTypeEnum, IClientInput, IMsgServerSync, InputTypeEnum, toFixed } from "../Common";
import EventManager from "../Global/EventManager";
import { deepClone } from "../Utils";
2022-11-27 23:23:47 +08:00
2022-12-01 22:26:41 +08:00
const { ccclass } = _decorator;
2022-11-27 23:23:47 +08:00
2022-12-08 21:14:02 +08:00
@ccclass("BattleManager")
2022-11-27 23:23:47 +08:00
export class BattleManager extends Component {
2022-12-08 21:14:02 +08:00
private stage: Node;
private ui: Node;
private shouldUpdate = false;
private pendingMsg = [];
async start() {
//清空
this.clearGame();
//资源加载和网络连接同步执行
await Promise.all([this.loadRes(), this.connectServer()]);
this.initGame();
// 在场景初始化完毕之前,卡主别的玩家,准备好以后再告知服务器,等所有玩家都准备好以后才开始,这里就不做了
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgServerSync, this.listenServerSync, this);
NetworkManager.Instance.listenMsg(ApiMsgEnum.MsgGameEnd, this.listenGameEnd, this);
EventManager.Instance.on(EventEnum.ClientSync, this.handleClientSync, this);
EventManager.Instance.on(EventEnum.GameEnd, this.handleGameEnd, this);
}
clearGame() {
//事件
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgServerSync, this.listenServerSync, this);
NetworkManager.Instance.unlistenMsg(ApiMsgEnum.MsgGameEnd, this.listenGameEnd, this);
EventManager.Instance.off(EventEnum.ClientSync, this.handleClientSync, this);
EventManager.Instance.off(EventEnum.GameEnd, this.handleGameEnd, this);
//数据
this.shouldUpdate = false;
ObjectPoolManager.Instance.reset();
DataManager.Instance.reset();
//节点
this.stage = DataManager.Instance.stage = this.node.getChildByName("Stage");
this.ui = this.node.getChildByName("UI");
this.stage.destroyAllChildren();
this.ui.destroyAllChildren();
}
async loadRes() {
const list = [];
for (const type in PrefabPathEnum) {
const p = ResourceManager.Instance.loadRes(PrefabPathEnum[type], Prefab).then((prefab) => {
DataManager.Instance.prefabMap.set(type, prefab);
});
list.push(p);
}
for (const type in TexturePathEnum) {
const p = ResourceManager.Instance.loadDir(TexturePathEnum[type], SpriteFrame).then((spriteFrames) => {
DataManager.Instance.textureMap.set(type, spriteFrames);
});
list.push(p);
}
await Promise.all(list);
}
async connectServer() {
if (!(await NetworkManager.Instance.connect().catch(() => false))) {
await new Promise((resolve) => setTimeout(resolve, 1000));
await this.connectServer();
}
}
async initGame() {
this.initJoyStick();
this.initShoot();
this.initMap();
this.shouldUpdate = true;
}
initJoyStick() {
const prefab = DataManager.Instance.prefabMap.get(EntityTypeEnum.JoyStick);
const joySitck = instantiate(prefab);
joySitck.setParent(this.ui);
const jm = (DataManager.Instance.jm = joySitck.getComponent(JoyStickManager));
jm.init();
}
initShoot() {
const prefab = DataManager.Instance.prefabMap.get(EntityTypeEnum.Shoot);
const shoot = instantiate(prefab);
shoot.setParent(this.ui);
}
initMap() {
const prefab = DataManager.Instance.prefabMap.get(EntityTypeEnum.Map1);
const map = instantiate(prefab);
map.setParent(this.stage);
}
update(dt: number) {
if (!this.shouldUpdate) {
return;
}
this.render();
this.tick(dt);
}
tick(dt: number) {
this.tickPlayer(dt);
// this.tickGlobal(dt)
}
tickPlayer(dt: number) {
for (const p of DataManager.Instance.state.actors) {
const playerManager = DataManager.Instance.actorMap.get(p.id);
if (!playerManager) {
return;
}
playerManager.tick(dt);
}
}
// tickGlobal(dt: number) {
// DataManager.Instance.applyInput({
// type: InputTypeEnum.TimePast,
// dt: toFixed(dt),
// })
// }
render() {
this.renderPlayer();
this.renderBullet();
}
renderPlayer() {
for (const p of DataManager.Instance.state.actors) {
let actorManager = DataManager.Instance.actorMap.get(p.id);
if (!actorManager) {
const playerPrefab = DataManager.Instance.prefabMap.get(p.type);
const player = instantiate(playerPrefab);
player.setParent(this.stage);
actorManager = player.addComponent(ActorManager);
DataManager.Instance.actorMap.set(p.id, actorManager);
actorManager.init(p);
} else {
actorManager.render(p);
}
}
}
renderBullet() {
for (const b of DataManager.Instance.state.bullets) {
let bulletManager = DataManager.Instance.bulletMap.get(b.id);
if (!bulletManager) {
const bullet = ObjectPoolManager.Instance.get(b.type);
bulletManager = bullet.getComponent(BulletManager) || bullet.addComponent(BulletManager);
DataManager.Instance.bulletMap.set(b.id, bulletManager);
bulletManager.init(b);
} else {
bulletManager.render(b);
}
}
}
handleClientSync(input: IClientInput) {
const msg = {
frameId: DataManager.Instance.frameId++,
input,
};
NetworkManager.Instance.sendMsg(ApiMsgEnum.MsgClientSync, msg);
//移动才做预测,射击不做
if (input.type === InputTypeEnum.ActorMove) {
DataManager.Instance.applyInput(input);
this.pendingMsg.push(msg);
}
}
listenServerSync({ lastFrameId, inputs }: IMsgServerSync) {
//回滚上次服务器状态
DataManager.Instance.state = DataManager.Instance.lastState;
//应用服务器输入
for (const input of inputs) {
DataManager.Instance.applyInput(input);
}
//记录最新的服务器状态
DataManager.Instance.lastState = deepClone(DataManager.Instance.state);
//过滤本地输入
this.pendingMsg = this.pendingMsg.filter((msg) => msg.frameId > lastFrameId);
//应用本地输入
for (const msg of this.pendingMsg) {
DataManager.Instance.applyInput(msg.input);
}
}
async handleGameEnd() {
const { success, res, error } = await NetworkManager.Instance.callApi(ApiMsgEnum.ApiGameEnd, { rid: DataManager.Instance.roomInfo.id });
if (!success) {
console.log(error);
return;
}
}
listenGameEnd() {
this.clearGame();
director.loadScene(SceneEnum.Hall);
}
2022-11-27 23:23:47 +08:00
}