GameMgr.ts 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. import { Game, director } from "cc";
  2. import { RoomMgr } from "../../module_basic/scripts/RoomMgr";
  3. import { UserMgr } from "../../module_basic/scripts/UserMgr";
  4. import { gameNet } from "../../module_basic/scripts/NetGameServer";
  5. import {
  6. IGameData,
  7. IGamePlayer,
  8. } from "../../module_basic/shared/protocols/public/game/GameTypeDef";
  9. import { MsgFoodAddedPush } from "../../module_basic/shared/protocols/public/game/MsgFoodAddedPush";
  10. import { MsgFoodEatenPush } from "../../module_basic/shared/protocols/public/game/MsgFoodEatenPush";
  11. import { MsgGameBeginPush } from "../../module_basic/shared/protocols/public/game/MsgGameBeginPush";
  12. import { MsgGameDataChangedPush } from "../../module_basic/shared/protocols/public/game/MsgGameDataChangedPush";
  13. import { MsgGameDataSyncPush } from "../../module_basic/shared/protocols/public/game/MsgGameDataSyncPush";
  14. import { MsgGameOverPush } from "../../module_basic/shared/protocols/public/game/MsgGameOverPush";
  15. import { MsgPlayerComesPush } from "../../module_basic/shared/protocols/public/game/MsgPlayerComesPush";
  16. import { MsgPlayerDataChangedPush } from "../../module_basic/shared/protocols/public/game/MsgPlayerDataChangedPush";
  17. import { MsgPlayerLeavesPush } from "../../module_basic/shared/protocols/public/game/MsgPlayerLeavesPush";
  18. import { MsgCellDataChange } from "../../module_basic/shared/protocols/public/game/MsgCellDataChange";
  19. export class GameEvent {
  20. public static PLAYER_COMES = "GameEvent.PLAYER_COMES";
  21. public static PLAYER_LEAVES = "GameEvent.PLAYER_LEAVES";
  22. public static PLAYER_DATA_CHANGED = "GameEvent.PLAYER_DATA_CHANGED";
  23. public static GAME_BEGIN = "GameEvent.GAME_BEGIN";
  24. public static GAME_OVER = "GameEvent.GAME_OVER";
  25. public static CELL_DATA_CHANGED = "GameEvent.CELL_DATA_CHANGED";
  26. public static FOOD_EATEN = "GameEvent.FOOD_EATEN";
  27. public static FOOD_ADDED = "GameEvent.FOOD_ADDED";
  28. public static PLAYER_DIE = "GameEvent.PLAYER_DIE";
  29. public static PLAYER_REVIVE = "GameEvent.PLAYER_REVIVE";
  30. public static GAME_DATA_CHANGED = "GameEvent.GAME_DATA_CHANGED";
  31. public static GAME_EXIT = "GameEvent.GAME_EXIT";
  32. }
  33. export class Skill {
  34. public static SKILL_1 = 1000;
  35. public static SKILL_2 = 1001;
  36. public id: number;
  37. public cd: number;
  38. }
  39. export class SillCastInfo {
  40. skill: Skill;
  41. lastCastTime: number;
  42. get isInCD() {
  43. let cdTime = this.lastCastTime + this.skill.cd - Date.now();
  44. return cdTime > 0;
  45. }
  46. get cdPercent() {
  47. let cdTime = this.lastCastTime + this.skill.cd - Date.now();
  48. if (cdTime <= 0) {
  49. return 0.0;
  50. }
  51. return cdTime / this.skill.cd;
  52. }
  53. }
  54. const skillMap = {};
  55. skillMap[Skill.SKILL_1] = { id: Skill.SKILL_1, cd: 2000 };
  56. skillMap[Skill.SKILL_2] = { id: Skill.SKILL_1, cd: 30000 };
  57. export class GameMgr {
  58. private static _inst: GameMgr;
  59. public static get inst(): GameMgr {
  60. if (!this._inst) {
  61. this._inst = new GameMgr();
  62. }
  63. return this._inst;
  64. }
  65. constructor() {
  66. this.initNetMsgHandlers();
  67. }
  68. public localGameOver() {
  69. this._gameData.gameState = "gameover";
  70. }
  71. public reset() {
  72. this._gameData = null;
  73. this._playerMap = {};
  74. this._skillCdMap = {};
  75. }
  76. private _gameData: IGameData;
  77. private _gameStateEndTime: number = 0;
  78. private _playerMap: { [key: number]: IGamePlayer } = {};
  79. private _skillCdMap: { [key: number]: SillCastInfo } = {};
  80. private _selfPlayer: IGamePlayer;
  81. public get selfPlayer(): IGamePlayer {
  82. return this._selfPlayer;
  83. }
  84. public localMode(p: IGameData) {
  85. this._gameData = p;
  86. }
  87. public get gameData(): Readonly<IGameData> {
  88. return this._gameData;
  89. }
  90. public get gameStateEndTime(): number {
  91. return this._gameStateEndTime;
  92. }
  93. public castSkill(skillId: number) {
  94. let skill = skillMap[skillId];
  95. if (!skill) {
  96. return false;
  97. }
  98. let cdInfo = this._skillCdMap[skillId];
  99. if (!cdInfo) {
  100. cdInfo = new SillCastInfo();
  101. cdInfo.skill = skill;
  102. cdInfo.lastCastTime = 0;
  103. this._skillCdMap[skillId] = cdInfo;
  104. }
  105. if (cdInfo.isInCD) {
  106. return false;
  107. }
  108. cdInfo.lastCastTime = Date.now();
  109. return true;
  110. }
  111. public getSkillCd(skillId: number) {
  112. return this._skillCdMap[skillId];
  113. }
  114. initNetMsgHandlers() {
  115. gameNet.listenMsg(
  116. "game/GameDataSyncPush",
  117. this.onNet_GameDataSyncPush,
  118. this
  119. );
  120. gameNet.listenMsg(
  121. "game/GameDataChangedPush",
  122. this.onNet_GameDataChangedPush,
  123. this
  124. );
  125. gameNet.listenMsg("game/PlayerComesPush", this.onNet_PlayerComesPush, this);
  126. gameNet.listenMsg(
  127. "game/PlayerDataChangedPush",
  128. this.onNet_PlayerDataChangedPush,
  129. this
  130. );
  131. gameNet.listenMsg(
  132. "game/PlayerLeavesPush",
  133. this.onNet_PlayerLeavesPush,
  134. this
  135. );
  136. gameNet.listenMsg("game/GameBeginPush", this.onNet_GameBeginPush, this);
  137. gameNet.listenMsg("game/GameOverPush", this.onNet_GameOverPush, this);
  138. gameNet.listenMsg("game/CellDataChange", this.onNet_CellDataChange, this);
  139. gameNet.listenMsg("game/FoodEatenPush", this.onNet_FoodEatenPush, this);
  140. gameNet.listenMsg("game/FoodAddedPush", this.onNet_FoodAddedPush, this);
  141. }
  142. sendMsg_CellDataChange(x: number, y: number, z: number, rotation: number) {
  143. gameNet.sendMsg("game/CellDataChange", { transform: [x, y, z, rotation] });
  144. }
  145. private get selfPlayerIndex(): number {
  146. return this.getPlayerIndex(UserMgr.inst.uid);
  147. }
  148. public get leftUserId(): string {
  149. if (!this._gameData || this._gameData.players.length == 0) {
  150. return "";
  151. }
  152. if (RoomMgr.inst.isPlayer) {
  153. return UserMgr.inst.uid;
  154. } else {
  155. return this._gameData.players[0].uid;
  156. }
  157. }
  158. public get rightUserId(): string {
  159. if (!this._gameData || this._gameData.players.length == 0) {
  160. return "";
  161. }
  162. if (RoomMgr.inst.isPlayer) {
  163. if (this._gameData.players[0].uid != UserMgr.inst.uid) {
  164. return this._gameData.players[0].uid;
  165. } else {
  166. let p = this._gameData.players[1];
  167. return p ? p.uid : "";
  168. }
  169. } else {
  170. let p = this._gameData.players[1];
  171. return p ? p.uid : "";
  172. }
  173. }
  174. public getPlayer(playerId: number): IGamePlayer {
  175. if (!this._gameData || !this._gameData.players) {
  176. return null;
  177. }
  178. for (let i = 0; i < this._gameData.players.length; ++i) {
  179. let p = this._gameData.players[i];
  180. if (p.playerId == playerId) {
  181. return p;
  182. }
  183. }
  184. return null;
  185. }
  186. private getPlayerIndex(userId: string): number {
  187. for (let i = 0; i < this._gameData.players.length; ++i) {
  188. if (this._gameData.players[i].uid == userId) {
  189. return i;
  190. }
  191. }
  192. return -1;
  193. }
  194. // ============= MESSAGE HANDLER ============
  195. /**
  196. * This message will arrive before login result.
  197. * 这个消息会在登录成功返回之前收到。
  198. */
  199. onNet_GameDataSyncPush(msg: MsgGameDataSyncPush) {
  200. this._gameData = msg.data;
  201. this._gameData.players.forEach((v) => {
  202. this._playerMap[v.playerId] = v;
  203. if (v.uid == UserMgr.inst.uid) {
  204. this._selfPlayer = v;
  205. }
  206. });
  207. this._gameStateEndTime = this._gameData.gameStateRemainingTime + Date.now();
  208. }
  209. onNet_GameDataChangedPush(msg: MsgGameDataChangedPush) {
  210. if (!this._gameData) {
  211. return;
  212. }
  213. if (msg.gameState != undefined) {
  214. this._gameData.gameState = msg.gameState;
  215. }
  216. if (msg.gameStateRemainingTime != undefined) {
  217. this._gameData.gameStateRemainingTime = msg.gameStateRemainingTime;
  218. this._gameStateEndTime =
  219. this._gameData.gameStateRemainingTime + Date.now();
  220. }
  221. if (msg.teamWeights != undefined) {
  222. for (let teamId in msg.teamWeights) {
  223. let score = msg.teamWeights[teamId];
  224. this._gameData.teamsWeights[teamId] = score;
  225. }
  226. }
  227. director.emit(GameEvent.GAME_DATA_CHANGED, msg);
  228. }
  229. onNet_PlayerComesPush(msg: MsgPlayerComesPush) {
  230. this._gameData.players.push(msg.player);
  231. this._playerMap[msg.player.playerId] = msg.player;
  232. if (msg.player.uid == UserMgr.inst.uid) {
  233. this._selfPlayer = msg.player;
  234. }
  235. director.emit(GameEvent.PLAYER_COMES, msg.player);
  236. }
  237. onNet_PlayerDataChangedPush(msg: MsgPlayerDataChangedPush) {
  238. let p = this.getPlayer(msg.playerId);
  239. if (!p) {
  240. return;
  241. }
  242. for (let k in msg) {
  243. p[k] = msg[k];
  244. }
  245. if (msg.reviveTime != undefined) {
  246. if (msg.reviveTime > 0) {
  247. director.emit(GameEvent.PLAYER_DIE, p);
  248. } else {
  249. director.emit(GameEvent.PLAYER_REVIVE, p);
  250. }
  251. }
  252. director.emit(GameEvent.PLAYER_DATA_CHANGED, msg);
  253. }
  254. onNet_PlayerLeavesPush(msg: MsgPlayerLeavesPush) {
  255. for (let i = 0; i < this._gameData.players.length; ++i) {
  256. let p = this._gameData.players[i];
  257. if (p.uid == msg.uid) {
  258. this._gameData.players.splice(i, 1);
  259. delete this._playerMap[p.playerId];
  260. director.emit(GameEvent.PLAYER_LEAVES, p);
  261. break;
  262. }
  263. }
  264. }
  265. onNet_GameBeginPush(msg: MsgGameBeginPush) {
  266. if (!this._gameData) {
  267. return;
  268. }
  269. this._gameData.players.forEach((v) => {
  270. //v.color = '';
  271. });
  272. director.emit(GameEvent.GAME_BEGIN);
  273. }
  274. onNet_GameOverPush(msg: MsgGameOverPush) {
  275. director.emit(GameEvent.GAME_OVER, msg);
  276. }
  277. onNet_CellDataChange(msg: MsgCellDataChange) {
  278. let p = this.getPlayer(msg.playerId);
  279. for (let k in msg) {
  280. p[k] = msg[k];
  281. }
  282. director.emit(GameEvent.CELL_DATA_CHANGED, msg);
  283. }
  284. onNet_FoodEatenPush(msg: MsgFoodEatenPush) {
  285. for (let i = 0; i < msg.eatenFoods.length; i++) {
  286. let foodId = msg.eatenFoods[i];
  287. delete this._gameData.foodList[foodId];
  288. }
  289. director.emit(GameEvent.FOOD_EATEN, msg);
  290. }
  291. onNet_FoodAddedPush(msg: MsgFoodAddedPush) {
  292. for (let i = 0; i < msg.foods.length; ++i) {
  293. let fd = msg.foods[i];
  294. this._gameData.foodList[fd.id] = fd;
  295. }
  296. director.emit(GameEvent.FOOD_ADDED, msg);
  297. }
  298. }
  299. GameMgr.inst;