WolfHuntGameMode_OnlinePK.cs 19 KB

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