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