WolfHuntGameMode_OnlinePK.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using Newtonsoft.Json;
  6. using DG.Tweening;
  7. /* 野狼关卡-联机pk模式 */
  8. public class WolfHuntGameMode_OnlinePK : WolfHuntGameMode, ChallengeGameModeLocalPK
  9. {
  10. public int currentPlayerIndex = 0; // 双人0和1
  11. float singleShootReadyTime = 30f;
  12. float singleShootReadyTimeMax = 30f;
  13. int[] playerHpList = {20, 20};
  14. public bool[] playerDieList = {false, false};
  15. public WolfHuntGameMode_OnlinePK(GameMgr gameMgr) : base(gameMgr) {
  16. onlineHelper = new OnlineHelper(this);
  17. hunterGamePlayerScoreCounter = new HunterGamePlayerScoreCounter(this);
  18. InitByCurPlayerIndex();
  19. GameEventCenter.ins.onBowArrowShootOut += (a, b) => {
  20. hasShootOut = true;
  21. //gameMgr.userGameAnalyse.changeShootingCount(1);
  22. };
  23. onHpZero += () => {//监听到当前玩家死亡
  24. playerDieList[currentPlayerIndex] = true;
  25. if (hasShootOut) return; //此时箭已射出,避免重复处理下面的逻辑,等NextShoot来处理
  26. //切换到下一个玩家
  27. if (IsOtherPlayerNotDie()) {
  28. ArmBow.ins.readyShoot();
  29. NextPlayerFinal();
  30. NextRound();
  31. } else { //游戏结束
  32. AnnounceGameOver();
  33. }
  34. };
  35. onHurtEffect += () => {
  36. try {
  37. onlineHelper.socketPlayer.UploadPKGameData("onHurtEffect", "");
  38. }
  39. catch (System.Exception e) { Debug.LogError(e.Message + "\n" + e.StackTrace); }
  40. };
  41. // this.playerHpList[0] = this.playerHpList[1] = this.hpMax = this.hp = 5;
  42. // QuicklyCreateAnimalForDebug();
  43. }
  44. public override void Start()
  45. {
  46. onlineHelper.InitSocketPlayer(OnStart);
  47. }
  48. private void OnStart() {
  49. banCreateAnimal = onlineHelper.IsCopyHost();
  50. banOnBowArrowShootOut = onlineHelper.IsCopyHost();
  51. GameMgr.ins.transform.Find("WolfActGrid").gameObject.SetActive(true);
  52. SetLevel(5);
  53. AddHuntGameView();
  54. this.gameMgr.transform.Find("HunterGameView_LocalPK").gameObject.SetActive(true);
  55. }
  56. public override void Update() {
  57. if (!onlineHelper.IsMyPlayerInited()) return;
  58. if (!onlineHelper.IsMainHost()) return;
  59. if (!onlineHelper.IsMyPlayerRunning()) return;
  60. OnUpdate(Time.deltaTime, pauseTimeCounting);
  61. }
  62. void OnUpdate(float dt, bool _pauseTimeCounting) {
  63. CheckAutoCreateAnimalByUpdate(dt);
  64. if (gameMgr.gameOver || _pauseTimeCounting) return;
  65. if (this.time > 0) {
  66. this.time -= dt;
  67. } else {
  68. this.time = 0;
  69. AnnounceGameOver();
  70. }
  71. if (gameMgr.gameOver || _pauseTimeCounting) return;
  72. if (!IsOtherPlayerNotDie()) { //另一个玩家已经死了,倒计时就不要走了
  73. singleShootReadyTime = singleShootReadyTimeMax;
  74. return;
  75. }
  76. singleShootReadyTime -= dt;
  77. if (singleShootReadyTime <= 0) {
  78. //切换玩家
  79. ArmBow.ins.readyShoot();
  80. NextPlayerFinal();
  81. NextRound();
  82. }
  83. }
  84. public override void FrameUpdate() {
  85. onlineHelper.OnFrameUpdate();
  86. }
  87. public override void onBowShoot() {
  88. if (onlineHelper.IsCopyHost()) {
  89. onlineHelper.socketPlayer.UploadPKGameData("onBowShoot", "");
  90. }
  91. }
  92. bool hasShootOut;
  93. public override bool DoNextShoot() {
  94. if (onlineHelper.IsCopyHost()) {
  95. onlineHelper.socketPlayer.UploadPKGameData("DoNextShoot", "");
  96. return false;
  97. }
  98. foreach (var item in Wolf.wolfSet) {
  99. if (item.onlineHandler.onDoNextShootWillDestroy) {
  100. GameObject.Destroy(item.gameObject);
  101. }
  102. }
  103. hasShootOut = false;
  104. if (IsAllPlayerDie()) {
  105. AnnounceGameOver();
  106. return false;
  107. }
  108. bool canDo = base.DoNextShoot();
  109. if (canDo && IsOtherPlayerNotDie()) {
  110. NextPlayerFinal();
  111. }
  112. if (canDo) {
  113. NextRound();
  114. }
  115. return canDo;
  116. }
  117. void AddReadyView()
  118. {
  119. GameObject view = Resources.Load<GameObject>("Prefabs/Views/PKGameReadyView_Challenge");
  120. GameObject o = GameObject.Instantiate(view);
  121. PKGameReadyView_Challenge script = o.GetComponent<PKGameReadyView_Challenge>();
  122. script.currentPlayerIndex = currentPlayerIndex;
  123. }
  124. void NextRound() {
  125. onlineHelper.roundID++;
  126. }
  127. //切换到下一个玩家
  128. void NextPlayerFinal() {
  129. NextPlayer();
  130. }
  131. void NextPlayer() {
  132. RecordByCurPlayerIndex();
  133. currentPlayerIndex = GetNextPlayerIndex();
  134. InitByCurPlayerIndex();
  135. singleShootReadyTime = singleShootReadyTimeMax;
  136. }
  137. int GetNextPlayerIndex() {
  138. return (currentPlayerIndex + 1) % 2;
  139. }
  140. bool IsAllPlayerDie() {
  141. return playerHpList[GetNextPlayerIndex()] <= 0 && hp <= 0;
  142. }
  143. bool IsOtherPlayerNotDie() {
  144. return playerHpList[GetNextPlayerIndex()] > 0;
  145. }
  146. void InitByCurPlayerIndex() {
  147. hp = playerHpList[currentPlayerIndex];
  148. HunterGameView v = GameObject.FindObjectOfType<HunterGameView>();
  149. if (v) v.RenderHPImmediate();
  150. }
  151. void RecordByCurPlayerIndex() {
  152. playerHpList[currentPlayerIndex] = hp;
  153. }
  154. //localPK interface
  155. public int GetCurrentPlayIndex() {
  156. return currentPlayerIndex;
  157. }
  158. public (float, float) GetSingleShootReadyTime() {
  159. return (singleShootReadyTime, singleShootReadyTimeMax);
  160. }
  161. HunterGamePlayerScoreCounter hunterGamePlayerScoreCounter;
  162. public HunterGamePlayerScoreCounter getHunterGamePlayerScoreCounter() {
  163. return hunterGamePlayerScoreCounter;
  164. }
  165. //###------------
  166. //### 联机部分
  167. //###------------
  168. public class SyncLogicData {
  169. public int roundID;
  170. public int currentPlayerIndex;
  171. public float singleShootReadyTime;
  172. public int animalCount = 0;
  173. public int[] hitScores;
  174. public int[] hpList;
  175. public int hp;
  176. public bool[] dieList;
  177. public bool gameEnd = false;
  178. public SyncLogicData Input(WolfHuntGameMode_OnlinePK src) {
  179. roundID = src.onlineHelper.roundID;
  180. currentPlayerIndex = src.currentPlayerIndex;
  181. singleShootReadyTime = src.singleShootReadyTime;
  182. animalCount = src.animalCount;
  183. hitScores = src.getHunterGamePlayerScoreCounter().hitScores;
  184. hpList = src.playerHpList;
  185. hp = src.hp;
  186. dieList = src.playerDieList;
  187. gameEnd = src.gameMgr.gameOver;
  188. return this;
  189. }
  190. public void Output(WolfHuntGameMode_OnlinePK dest) {
  191. dest.onlineHelper.roundID = roundID;
  192. dest.currentPlayerIndex = currentPlayerIndex;
  193. dest.singleShootReadyTime = singleShootReadyTime;
  194. dest.animalCount = animalCount;
  195. dest.getHunterGamePlayerScoreCounter().hitScores = hitScores;
  196. dest.playerHpList = hpList;
  197. dest.hp = hp;
  198. dest.playerDieList = dieList;
  199. dest.onlineHelper.gameEnd = gameEnd;
  200. }
  201. }
  202. OnlineHelper onlineHelper;
  203. public class OnlineHelper {
  204. WolfHuntGameMode_OnlinePK gameMode;
  205. public OnlineHelper(WolfHuntGameMode_OnlinePK gameMode) {
  206. this.gameMode = gameMode;
  207. }
  208. public SocketPlayer socketPlayer;
  209. public int myPlayerIndex = -1;
  210. public bool IsMyPlayerInited() {
  211. return myPlayerIndex >= 0;
  212. }
  213. public bool IsMyPlayerRunning() {
  214. return myPlayerIndex == gameMode.currentPlayerIndex;
  215. }
  216. public bool IsMainHost() {
  217. return myPlayerIndex == 0;
  218. }
  219. public bool IsCopyHost() {
  220. return myPlayerIndex > 0;
  221. }
  222. public int roundID = 0;
  223. public bool gameEnd = false;
  224. public void InitSocketPlayer(Action successCallback) {
  225. socketPlayer = SocketPlayer.NewInstance();
  226. socketPlayer.onRoomReadyComplete = () => {
  227. myPlayerIndex = GlobalData.playerIndexInRoom;
  228. if (successCallback != null) successCallback();
  229. };
  230. socketPlayer.onReceivePKGameData = onReceivePKGameData;
  231. AutoSwitchBanUserControlBow();
  232. JCUnityLib.CoroutineStarter.Start(CheckAndUpload());
  233. }
  234. bool IsCanUpload() {
  235. return GameMgr.ins == gameMode.gameMgr && gameMode.gameMgr;
  236. }
  237. WaitForSecondsRealtime uploadOnceTime = new WaitForSecondsRealtime(0.033f);
  238. IEnumerator CheckAndUpload() {
  239. Debug.Log("协程-同步数据-开始");
  240. while (IsCanUpload()) {
  241. try
  242. {
  243. Upload();
  244. }
  245. catch (System.Exception e)
  246. {
  247. Debug.LogError(e.Message);
  248. Debug.LogError(e.StackTrace);
  249. }
  250. yield return uploadOnceTime;
  251. }
  252. Debug.Log("协程-同步数据-停止");
  253. }
  254. Quaternion bowTargetQua;
  255. bool hasBowTargBtQua;
  256. void onReceivePKGameData(string key, string data) {
  257. if (!IsMyPlayerInited()) return;
  258. if (key == "logic") {
  259. SyncLogicData syncLogicData = JsonConvert.DeserializeObject<SyncLogicData>(data);
  260. syncLogicData.Output(this.gameMode);
  261. AutoSwitchBanUserControlBow();
  262. }
  263. if (key == "bow") {
  264. if (!IsMyPlayerRunning()) {
  265. string[] quaStr = data.Split(',');
  266. if (quaStr.Length == 6) {
  267. bowTargetQua.x = float.Parse(quaStr[0]);
  268. bowTargetQua.y = float.Parse(quaStr[1]);
  269. bowTargetQua.z = float.Parse(quaStr[2]);
  270. bowTargetQua.w = float.Parse(quaStr[3]);
  271. hasBowTargBtQua = true;
  272. ArmBow.ins.phase = int.Parse(quaStr[4]);
  273. GameAssistUI.ins.playerScaleAimValue_OnlinePK = int.Parse(quaStr[5]);
  274. }
  275. }
  276. }
  277. if (key == "arrow") {
  278. List<ArrowSync.SyncData> arrowSyncDataList = JsonConvert.DeserializeObject<List<ArrowSync.SyncData>>(data);
  279. foreach (var item in arrowSyncMap) {
  280. item.Value.hasSetSyncData = false;
  281. }
  282. GameObject arrowPrefab = ArmBow.ins.arrow;
  283. foreach (var item in arrowSyncDataList) {
  284. ArrowSync arrowSync;
  285. arrowSyncMap.TryGetValue(item.id, out arrowSync);
  286. if (arrowSync == null) {
  287. GameObject arrowObj = GameObject.Instantiate(arrowPrefab);
  288. arrowSync = arrowObj.AddComponent<ArrowSync>();
  289. arrowSync.SetSyncData(item, true);
  290. arrowSyncMap[item.id] = arrowSync;
  291. } else {
  292. arrowSync.SetSyncData(item);
  293. }
  294. arrowSync.hasSetSyncData = true;
  295. }
  296. List<int> removeIDs = null;
  297. foreach (var item in arrowSyncMap) {
  298. if (!item.Value.hasSetSyncData) {
  299. if (removeIDs == null) removeIDs = new List<int>();
  300. removeIDs.Add(item.Key);
  301. }
  302. }
  303. if (removeIDs != null) {
  304. foreach (var id in removeIDs) {
  305. ArrowSync arrowSync = arrowSyncMap[id];
  306. arrowSyncMap.Remove(id);
  307. if (arrowSync && arrowSync.gameObject) {
  308. GameObject.Destroy(arrowSync.gameObject);
  309. }
  310. }
  311. }
  312. }
  313. if (key == "onBowShoot") {
  314. GameEventCenter.ins.onBowArrowShootOut?.Invoke(null, null);
  315. }
  316. if (key == "DoNextShoot") {
  317. gameMode.DoNextShoot();
  318. }
  319. if (key == "animals") {
  320. List<WolfSyncData> syncDataList = JsonConvert.DeserializeObject<List<WolfSyncData>>(data);
  321. foreach (var item in animalSyncMap) {
  322. item.Value.onlineHandler.isInvalid = true;
  323. }
  324. foreach (var item in syncDataList) {
  325. Wolf animalSync;
  326. animalSyncMap.TryGetValue(item.id, out animalSync);
  327. if (animalSync == null) {
  328. GameObject animalObject = GameObject.Instantiate(gameMode.animalPrefab, Vector3.zero, Quaternion.identity, gameMode.animalsBaseT);
  329. animalSync = animalObject.GetComponent<Wolf>();
  330. animalSync.onlineHandler.isMirror = true;
  331. animalSync.onlineHandler.inputSyncData = item;
  332. animalObject.SetActive(true);
  333. animalSyncMap[item.id] = animalSync;
  334. } else {
  335. animalSync.onlineHandler.inputSyncData = item;
  336. }
  337. animalSync.onlineHandler.isInvalid = false;
  338. }
  339. List<int> removeIDs = null;
  340. foreach (var item in animalSyncMap) {
  341. if (item.Value.onlineHandler.isInvalid) {
  342. if (removeIDs == null) removeIDs = new List<int>();
  343. removeIDs.Add(item.Key);
  344. }
  345. }
  346. if (removeIDs != null) {
  347. foreach (var id in removeIDs) {
  348. Wolf animalSync = animalSyncMap[id];
  349. animalSyncMap.Remove(id);
  350. if (animalSync && animalSync.gameObject) {
  351. GameObject.Destroy(animalSync.gameObject);
  352. }
  353. }
  354. }
  355. }
  356. if (key == "RUpdate") {
  357. if (int.Parse(data) == roundID) {
  358. gameMode.OnUpdate(uploadOnceTime.waitTime, false);
  359. }
  360. }
  361. if (key == "OnHit") {
  362. string[] dataSplits = data.Split(',');
  363. int uid = int.Parse(dataSplits[0]);
  364. string partName = dataSplits[1];
  365. foreach (var item in Wolf.wolfSet) {
  366. if (item.onlineHandler.uid == uid) {
  367. item.OnHitLogic(null, partName);
  368. break; //一定要break,原因1:这是唯一ID,后续也没必要检测了,原因2:这里可能会触发死亡,死亡会触发下个动物生成,Set集合的元素+1,继续遍历会出现modifyException
  369. }
  370. }
  371. }
  372. if (key == "onHurtEffect") {
  373. this.gameMode.DoTweenHurt();
  374. }
  375. }
  376. public void AutoSwitchBanUserControlBow() {
  377. BowCamera.ins.banLogic = ArmBow.ins.banLogic = !IsMyPlayerRunning();
  378. }
  379. int lastRoundID = -1;
  380. int lastRoundTipPlayerIndex = -1; //是否需要切换玩家,提示动画
  381. public void OnFrameUpdate() {
  382. if (!IsMyPlayerInited()) return;
  383. AutoSwitchBanUserControlBow();
  384. if (!IsMyPlayerRunning() && hasBowTargBtQua) {
  385. BowCamera.ins.transform.rotation = Quaternion.Lerp(BowCamera.ins.transform.rotation, bowTargetQua, Time.deltaTime * 12);
  386. }
  387. if (roundID > lastRoundID) {
  388. lastRoundID = roundID;
  389. if (lastRoundTipPlayerIndex != gameMode.currentPlayerIndex) {
  390. lastRoundTipPlayerIndex = gameMode.currentPlayerIndex;
  391. gameMode.BanBowReady();
  392. gameMode.AddReadyView();
  393. gameMode.InitByCurPlayerIndex();
  394. } else {
  395. if (IsCopyHost()) {
  396. gameMode.UnbanBowReady();
  397. }
  398. }
  399. }
  400. if (gameEnd && !gameMode.gameMgr.gameOver) {
  401. gameMode.AnnounceGameOver();
  402. }
  403. }
  404. void Upload() {
  405. if (!IsMyPlayerInited()) return;
  406. UploadLogic();
  407. UploadBow();
  408. UploadArrows();
  409. UploadAnimals();
  410. UploadRequestUpdate();
  411. UploadOnHit();
  412. }
  413. void UploadLogic() {
  414. if (!IsMainHost()) return;
  415. SyncLogicData data = new SyncLogicData().Input(this.gameMode);
  416. socketPlayer.UploadPKGameData("logic", data);
  417. }
  418. void UploadBow() {
  419. if (!IsMyPlayerRunning()) return;
  420. Quaternion qua = BowCamera.ins.transform.rotation;
  421. int aimScaleValue = GameAssistUI.ins.aimScaleValue;
  422. if (!GameAssistUI.ins.scaleAimOn) aimScaleValue = 0;
  423. socketPlayer.UploadPKGameData("bow", qua.x + "," + qua.y + "," + qua.z + "," + qua.w + "," + ArmBow.ins.phase + "," + aimScaleValue);
  424. }
  425. Dictionary<int, ArrowSync> arrowSyncMap = new Dictionary<int, ArrowSync>();
  426. void UploadArrows() {
  427. List<ArrowSync.SyncData> arrowSyncDataList = new List<ArrowSync.SyncData>();
  428. foreach (var item in Arrow.arrowSet) {
  429. if (item.outputSyncData == null || !item.outputSyncData.inited) continue;
  430. arrowSyncDataList.Add(item.outputSyncData);
  431. }
  432. socketPlayer.UploadPKGameData("arrow", arrowSyncDataList);
  433. }
  434. Dictionary<int, Wolf> animalSyncMap = new Dictionary<int, Wolf>();
  435. void UploadAnimals() {
  436. if (!IsMainHost()) return;
  437. List<WolfSyncData> syncDataList = new List<WolfSyncData>();
  438. foreach (var item in Wolf.wolfSet) {
  439. if (item.onlineHandler.outputSyncData == null) continue;
  440. syncDataList.Add(item.onlineHandler.outputSyncData);
  441. }
  442. socketPlayer.UploadPKGameData("animals", syncDataList);
  443. }
  444. void UploadRequestUpdate() {
  445. if (!IsCopyHost()) return;
  446. if (!IsMyPlayerRunning()) return;
  447. if (gameMode.pauseTimeCounting) return;
  448. socketPlayer.UploadPKGameData("RUpdate", this.roundID.ToString());
  449. }
  450. void UploadOnHit() {
  451. foreach (var item in Wolf.wolfSet) {
  452. if (item.onlineHandler.onHitData != null) {
  453. socketPlayer.UploadPKGameData("OnHit", item.onlineHandler.onHitData);
  454. item.onlineHandler.onHitData = null;
  455. }
  456. }
  457. }
  458. }
  459. }