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
|
|
|
}
|