using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using DG.Tweening; using Newtonsoft.Json; /* 静止靶-联机pk模式 */ public class PKGameMode_OnlinePK : GameMode { SocketPlayer socketPlayer; public int myPlayerIndex = -111; public bool IsMyPlayerInited() { return myPlayerIndex >= 0; } public bool IsMyPlayerRunning() { return myPlayerIndex == gameLogic.currentPlayerIndex; } public PKGameMode_OnlinePK(GameMgr gameMgr) : base(gameMgr) { GlobalData.pkMatchType = PKMatchType.OnlinePK; socketPlayer = SocketPlayer.NewInstance(); socketPlayer.onRoomReadyComplete = () => { myPlayerIndex = GlobalData.playerIndexInRoom; ToInitGameView(); }; socketPlayer.onReceivePKGameData = onReceivePKGameData; gameLogic.InitAppearPlayerIndexes(); gameLogic.SetCurrentPlayerIndexToNext(); //记录可射击的靶子 targetBody = GameObject.Find("GameArea/TargetObject/TargetBody").GetComponent(); GameObject.FindObjectOfType().validTargets.Add(targetBody); //禁止动作-相机和手臂 BanBowReady(); AutoSwitchBanUserControlBow(); } void ToInitGameView() { //添加游戏界面 GameObject view = Resources.Load("Prefabs/Views/PKGameView"); GameObject.Instantiate(view); } Quaternion bowTargetQua; bool hasBowTargBtQua; void onReceivePKGameData(string key, string data) { if (key == "logic") { GameLogic gameLogic = JsonConvert.DeserializeObject(data); if ( (gameLogic.nextPlayerExcuteID == this.gameLogic.nextPlayerExcuteID && myPlayerIndex != gameLogic.currentPlayerIndex) || (gameLogic.nextPlayerExcuteID > this.gameLogic.nextPlayerExcuteID) ) { this.gameLogic = gameLogic; AutoSwitchBanUserControlBow(); } } if (key == "bow") { if (!IsMyPlayerRunning()) { string[] quaStr = data.Split(','); if (quaStr.Length == 6) { bowTargetQua.x = float.Parse(quaStr[0]); bowTargetQua.y = float.Parse(quaStr[1]); bowTargetQua.z = float.Parse(quaStr[2]); bowTargetQua.w = float.Parse(quaStr[3]); hasBowTargBtQua = true; ArmBow.ins.phase = int.Parse(quaStr[4]); GameAssistUI.ins.playerScaleAimValue_OnlinePK = int.Parse(quaStr[5]); } } } if (key == "arrow") { List arrowSyncDataList = JsonConvert.DeserializeObject>(data); foreach (var item in arrowSyncMap) { item.Value.hasSetSyncData = false; } GameObject arrowPrefab = ArmBow.ins.arrow; foreach (var item in arrowSyncDataList) { ArrowSync arrowSync; arrowSyncMap.TryGetValue(item.id, out arrowSync); if (arrowSync == null) { GameObject arrowObj = GameObject.Instantiate(arrowPrefab); arrowSync = arrowObj.AddComponent(); arrowSync.SetSyncData(item, true); arrowSyncMap[item.id] = arrowSync; } else { arrowSync.SetSyncData(item); } arrowSync.hasSetSyncData = true; } List removeIDs = null; foreach (var item in arrowSyncMap) { if (!item.Value.hasSetSyncData) { if (removeIDs == null) removeIDs = new List(); removeIDs.Add(item.Key); } } if (removeIDs != null) { foreach (var id in removeIDs) { ArrowSync arrowSync = arrowSyncMap[id]; arrowSyncMap.Remove(id); if (arrowSync && arrowSync.gameObject) { GameObject.Destroy(arrowSync.gameObject); } } } } if (key == "score") { HitTargetNumber.Create(float.Parse(data)); } if (key == "shootSpeed") { Billboard.ins?.SetShootSpeedText(data); } } void AutoSwitchBanUserControlBow() { BowCamera.ins.banLogic = ArmBow.ins.banLogic = !IsMyPlayerRunning(); } //记录可射击的靶子 TargetBody targetBody; bool hasStart = false; public override void Start() { hasStart = true; TargetView.ins.Show(true); } void AddReadyView() { GameObject view = Resources.Load("Prefabs/Views/PKGameReadyView"); GameObject.Instantiate(view); } public override void HitTarget(float score) { gameLogic.HitTarget(score); HitTargetNumber.Create(score); scoreWillSend = score.ToString(); } public override bool DoNextShoot() { return gameLogic.DoNextShoot(this); } public override object[] Settle() { return gameLogic.gameRes; } float uploadGameDataTime = 0; float uploadBowTime = 0; public override void Update() { if (!IsMyPlayerInited()) return; if (!hasStart) return; AutoSwitchBanUserControlBow(); if (IsMyPlayerRunning()) { gameLogic.Update(this); upload1(); } upload2(); gameDisplay.Update(this); } Dictionary arrowSyncMap = new Dictionary(); void upload1() { uploadBowTime -= Time.deltaTime; if (uploadBowTime <= 0) { uploadBowTime = 0.033f; Quaternion qua = BowCamera.ins.transform.rotation; int aimScaleValue = GameAssistUI.ins.aimScaleValue; if (!GameAssistUI.ins.scaleAimOn) aimScaleValue = 0; socketPlayer.UploadPKGameData("bow", qua.x + "," + qua.y + "," + qua.z + "," + qua.w + "," + ArmBow.ins.phase + "," + aimScaleValue); } } string scoreWillSend = null; public string shootSpeedWillSend = null; void upload2() { uploadGameDataTime -= Time.deltaTime; if (uploadGameDataTime <= 0) { uploadGameDataTime = 0.033f; socketPlayer.UploadPKGameData("logic", gameLogic); List arrowSyncDataList = new List(); foreach (var item in Arrow.arrowSet) { if (item.outputSyncData == null || !item.outputSyncData.inited) continue; arrowSyncDataList.Add(item.outputSyncData); } socketPlayer.UploadPKGameData("arrow", arrowSyncDataList); if (scoreWillSend != null) { socketPlayer.UploadPKGameData("score", scoreWillSend); scoreWillSend = null; } if (shootSpeedWillSend != null) { socketPlayer.UploadPKGameData("shootSpeed", shootSpeedWillSend); shootSpeedWillSend = null; } } } public override void onBowReady() { if (!IsMyPlayerRunning()) return; gameLogic.singleShootReadyTime = gameLogic.singleShootReadyMaxTime; gameLogic.singleShootTimeRunning = true; } public override void onBowShoot() { if (!IsMyPlayerRunning()) return; gameLogic.singleShootTimeRunning = false; } //gamelogic-data public GameLogic gameLogic = new GameLogic(); public class GameLogic { public int currentPlayerIndex = 0; public int[] totalScores = {0, 0}; public float[] currentScores = {0, 0}; public int round = 1; public int maxRound = 5; public int[] shootCount = {0, 0}; public int maxShootCount = 3; public float singleShootReadyTime = 20; public float singleShootReadyMaxTime = 20; public bool singleShootTimeRunning = false; public string[] gameRes = {"平局", "平局"}; public bool gameEnd = false; //玩家出场顺序 public List appearPlayerIndexes = new List(); //这里不用Queue,是因为IL2CPP环境下json反序列化失败 public int[] sequencePlayerIndexes = new int[]{0, 1}; public int nextPlayerExcuteID = 0; public void InitAppearPlayerIndexes() { if (round >= 2) { if (totalScores[0] < totalScores[1]) { sequencePlayerIndexes = new int[]{0, 1}; } else if (totalScores[1] < totalScores[0]) { sequencePlayerIndexes = new int[]{1, 0}; } } for (int i = 0; i < maxShootCount; i++) { appearPlayerIndexes.Add(sequencePlayerIndexes[0]); appearPlayerIndexes.Add(sequencePlayerIndexes[1]); } } public void SetCurrentPlayerIndexToNext() { currentPlayerIndex = appearPlayerIndexes[0]; appearPlayerIndexes.RemoveAt(0); nextPlayerExcuteID++; } public void Update(PKGameMode_OnlinePK gm) { if (singleShootTimeRunning && !gm.pauseTimeCounting) { singleShootReadyTime -= Time.deltaTime; if (singleShootReadyTime <= 0) { singleShootReadyTime = 0; singleShootTimeRunning = false; HitTarget(0); // BanBowReady(); // //超时显示 // Text timeoutText = PKGameView.ins.transform.Find("TimeoutText").GetComponent(); // Sequence seq = DOTween.Sequence(); // seq.Append(timeoutText.DOFade(1, 0.5f)); // seq.AppendInterval(1); // seq.Append(timeoutText.DOFade(0, 0.5f)); // seq.AppendCallback(delegate(){ // if (DoNextShoot()) { // UnbanBowReady(); // } // }); DoNextShoot(gm); } } } public void HitTarget(float score) { currentScores[currentPlayerIndex] += score; shootCount[currentPlayerIndex]++; } public bool DoNextShoot(PKGameMode_OnlinePK gm) { if (gm.gameMgr.gameOver) return false; bool nextRound = false; if (shootCount[0] == maxShootCount && shootCount[1] == maxShootCount ) { shootCount = new int[]{0, 0}; nextRound = true; //更新总比分 if (currentScores[0] == currentScores[1]) { totalScores[0] += 1; totalScores[1] += 1; } else if (currentScores[0] > currentScores[1]) { totalScores[0] += 2; } else if (currentScores[0] < currentScores[1]) { totalScores[1] += 2; } //根据总比分判断游戏是否结束 if (totalScores[0] == totalScores[1]) { if (round == maxRound) { if (round == 5) { maxShootCount = 1; maxRound = 6; } else { gameEnd = true; gameRes = new string[]{"平局", "平局"}; } } } else if (totalScores[0] >= 6 && totalScores[0] > totalScores[1]) { gameEnd = true; gameRes = new string[]{"胜利", "失败"}; } else if (totalScores[1] >= 6 && totalScores[1] > totalScores[0]) { gameEnd = true; gameRes = new string[]{"失败", "胜利"}; } } if (gameEnd) { return false; } else { //进入下一回合? if (nextRound) { round++; currentScores[0] = currentScores[1] = 0; InitAppearPlayerIndexes(); } //本轮玩家登记 SetCurrentPlayerIndexToNext(); gm.BanBowReady(); } return true; } } //game-display public GameDisplay gameDisplay = new GameDisplay(); public class GameDisplay { readonly float[] targetDistancesOnRound = {10, 20, 30, 50, 70, 70}; public int[] playerRoleIDs = {1, 2}; public int showRoundValueOnReadyView = 0; #region 用于控制显示更新的变量 int round = 0; int nextPlayerExcuteID = 0; bool gameEnd = false; #endregion public void Update(PKGameMode_OnlinePK gm) { if (round != gm.gameLogic.round) { round = gm.gameLogic.round; gm.targetBody.SetDistance(targetDistancesOnRound[round - 1]); } if (nextPlayerExcuteID != gm.gameLogic.nextPlayerExcuteID) { nextPlayerExcuteID = gm.gameLogic.nextPlayerExcuteID; gm.BanBowReady(); gm.AddReadyView(); //清除箭矢 foreach (var arrow in Arrow.arrowSet) { try { GameObject.Destroy(arrow.gameObject); } catch (UnityException e) { Debug.Log("Delete Arrow Error\n" + e.Message); } } } if (!gameEnd && gm.gameLogic.gameEnd) { gameEnd = true; gm.gameMgr.StopGame(); GameObject view = Resources.Load("Prefabs/Views/PKGameSettleView"); GameObject.Instantiate(view); } if (!gm.IsMyPlayerRunning() && gm.hasBowTargBtQua) { BowCamera.ins.transform.rotation = Quaternion.Lerp(BowCamera.ins.transform.rotation, gm.bowTargetQua, Time.deltaTime * 12); } } } }