using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; namespace DuckHunter { public class GameManager : MonoBehaviour { public static GameManager Instance; [SerializeField] GameObject dogObject; [SerializeField] GameObject dogSideObject; [SerializeField] GameObject duckPrefab; [SerializeField] RectTransform duckBox; [System.NonSerialized] public bool isGameStarted; [System.NonSerialized] public bool isGameOver; public bool isGamePlaying { get => isGameStarted && !isGameOver; } public System.Action onGameStart; public UserGameAnalyse1 userGameAnalyse1; void Awake() { Instance = this; dogObject.SetActive(true); if (!AutoNextLevel) { //如果调试页面存在,使用duckHunterLevel DefaultLevel = InfraredDemo._ins ? (int)InfraredDemo._ins.duckHunterLevel.Get(): 1; _CumulativeScore = 0; } level = DefaultLevel; uploadScore = 0; } void OnDestroy() { if (Instance == this) Instance = null; } void Start() { TextGameScreenCenter.Instance.ShowText(TextGameScreenCenter.TextName.GAME_START); if (AutoNextLevel) { AutoNextLevel = false; StartGame(true); } userGameAnalyse1 = UserGameAnalyse1.CreateWhenGameStartAndReturn(13); } void Update() { UpdateCheckMouseHit(); UpdateForAutoCreateDucks(); SettleGame(); #if UNITY_EDITOR if (Input.GetKeyDown(KeyCode.A)) { Time.timeScale = 10; } if (Input.GetKeyUp(KeyCode.A)) { Time.timeScale = 1; } #endif } void UpdateCheckMouseHit() { if (Input.GetMouseButtonDown(0) && BowCamera.isTouchMode) { if (EventSystem.current.currentSelectedGameObject == null) { CrossHair.Instance.transform.position = Input.mousePosition; OnModuleShooting(10); } } } /// /// 基础初速度 /// public static float BaseFlySpeed = 50; /// /// 下次从多少分开始 /// public static int DefaultLevel = 1; private static bool AutoNextLevel = false; [System.NonSerialized] public int hitScore; //得分 private int uploadScore;//上传服务器的分数 private bool bAddCountScore = false; [System.NonSerialized] public int level = 1; /// /// 通关需要击落的鸭子数量 /// int passNeedHitCount; int needCreateDuckCount; bool canCreateDuck; [System.NonSerialized] public int theDuckCountWaitingForDogHandle; float _createDuckInterval; void UpdateForAutoCreateDucks() { if (isGameOver) return; if (!canCreateDuck) return; _createDuckInterval = 0; if (level <= 9)//60 { if (theDuckCountWaitingForDogHandle > 0) return; } else if (level <= 13)//80 { if (theDuckCountWaitingForDogHandle > 0) _createDuckInterval = 5; if (theDuckCountWaitingForDogHandle > 1) return; } else //<=100 { if (theDuckCountWaitingForDogHandle > 0) _createDuckInterval = 5; if (theDuckCountWaitingForDogHandle > 2) return; } if (!Dog.Instance || Dog.Instance.isShowing) return; if (Time.time - _lastCreateDuckTime < _createDuckInterval) return; CreateDuck(); } List _ductTypeList = null; /// /// 生成野鸭,并且打乱数组 /// /// 绿色数量 /// 蓝色数量 /// 红色数量 void InitDuckTypeList(int greenCount, int blueCount, int redCount) { if (_ductTypeList != null) return; _ductTypeList = new List(); for (int i = 0; i < greenCount; i++) _ductTypeList.Add(1); for (int i = 0; i < blueCount; i++) _ductTypeList.Add(4);//2 for (int i = 0; i < redCount; i++) _ductTypeList.Add(3); _ductTypeList.Sort((a, b) => Random.value < 0.5 ? -1 : 1); needCreateDuckCount = _ductTypeList.Count; } static float[] _FlyAngles1 = { 75, 180 - 75 }; static float[] _FlyAngles2 = { 75, 60, 180 - 75, 180 - 60 }; static float[] _FlyAngles3 = { 45, 60, 180 - 45, 180 - 60 }; static float[] _FlyAngles4 = { 30, 45, 60, 180 - 30, 180 - 45, 180 - 60 }; static float RangeFlyAngle(float[] angles) { return angles[Random.Range(0, angles.Length)]; } DuckConfig GetDuckConfig() { DuckConfig duckConfig = new DuckConfig(); if (level <= 20) duckConfig.positionX = Random.Range(duckBox.rect.width / 2 - 200, duckBox.rect.width / 2 + 50); else duckConfig.positionX = Random.Range(250, duckBox.rect.width - 350); // ● 三关,每关至少击中6只野鸭,同屏1只 // ● 遇到4次边框未被击中 // ● 三箭(枪)用尽未被击中 // ● 绿色野鸭 if (level <= 3)//10 { InitDuckTypeList(10, 0, 0); passNeedHitCount = 6; duckConfig.touchBoundCount = 4; duckConfig.flyAngle = RangeFlyAngle(_FlyAngles1); } // ● 三关,每关至少击中7只野鸭,同屏1只 // ● 遇到5次边框未被击中 // ● 三箭(枪)用尽未被击中 // ● 蓝色野鸭 else if (level <= 6)//15 { InitDuckTypeList(0, 10, 0);// InitDuckTypeList(5, 5, 0); passNeedHitCount = 7; duckConfig.touchBoundCount = 5; duckConfig.flyAngle = RangeFlyAngle(_FlyAngles1); } // ● 三关,每关至少击中8只野鸭,同屏1只 // ● 遇到6次边框未被击中 // ● 三箭(枪)用尽未被击中 // ● 红色野鸭 else if (level <= 9)//18 { InitDuckTypeList(0, 0, 10);//InitDuckTypeList(5, 3, 2); passNeedHitCount = 8; duckConfig.touchBoundCount = 6; duckConfig.flyAngle = RangeFlyAngle(_FlyAngles1); } // ● 两关,每关至少击中9只野鸭,同屏2只,第二只5秒 // ● 遇到7次边框未被击中 // ● 三箭(枪)用尽未被击中 // ● 绿 ,蓝野鸭 else if (level <= 11) { InitDuckTypeList(5, 5, 0); passNeedHitCount = 9; duckConfig.touchBoundCount = 7; duckConfig.flyAngle = RangeFlyAngle(_FlyAngles1); } // ● 两关,每关至少击中9只野鸭,同屏2只,第二只5秒 // ● 遇到7次边框未被击中 // ● 三箭(枪)用尽未被击中 // ● 蓝,红野鸭 else if (level <= 13) { InitDuckTypeList(0, 5, 5); passNeedHitCount = 9; duckConfig.touchBoundCount = 7; duckConfig.flyAngle = RangeFlyAngle(_FlyAngles1); } // ● 14-20关,每关至少击中10只野鸭,同屏3只,第二只5秒,第三只10秒。 // ● 遇到8次边框未被击中 // ● 三箭(枪)用尽未被击中 // ● 绿、蓝、红野鸭 else { InitDuckTypeList(3, 4, 3); passNeedHitCount = 10; duckConfig.touchBoundCount = 8; duckConfig.flyAngle = RangeFlyAngle(_FlyAngles2); } //else if (level <= 60) //{ // InitDuckTypeList(3, 3, 4); // passNeedHitCount = 10; // duckConfig.touchBoundCount = 6; // duckConfig.flyAngle = RangeFlyAngle(_FlyAngles3); //} //else if (level <= 80) //{ // InitDuckTypeList(2, 4, 4); // passNeedHitCount = 10; // duckConfig.touchBoundCount = 7; // duckConfig.flyAngle = RangeFlyAngle(_FlyAngles4); //} //else if (level <= 100) //{ // InitDuckTypeList(2, 3, 5); // passNeedHitCount = 10; // duckConfig.touchBoundCount = 8; // duckConfig.flyAngle = RangeFlyAngle(_FlyAngles4); //} duckConfig.type = _ductTypeList[0]; _ductTypeList.RemoveAt(0); //duckConfig.flySpeed = BaseFlySpeed * (1 + (level - 1) * 0.05f); //2023-7-25修改:速度还是以80关的做为初始速度,后面的关卡再按原来的公式增加 duckConfig.flySpeed = BaseFlySpeed * (1 + (level + 79 - 1) * 0.05f); if (duckConfig.type == 1) duckConfig.flySpeed *= 1f; else if (duckConfig.type == 4) duckConfig.flySpeed *= 1.2f; //duckConfig.type == 2 else if (duckConfig.type == 3) duckConfig.flySpeed *= 1.5f; return duckConfig; } float _lastCreateDuckTime = -1000; void CreateDuck() { if (_ductTypeList != null && _ductTypeList.Count == 0) return; theDuckCountWaitingForDogHandle++; _lastCreateDuckTime = Time.time; DuckConfig duckConfig = GetDuckConfig(); Duck duck = Instantiate(duckPrefab, duckBox).GetComponent(); duck.config = duckConfig; duck.onExit += HandleOnDuckExit; duck.onFallDonwEnd += HandleOnDuckFallDown; duck.onHitDead += HandleOnHitDead; duck.onStartFlyAway += () => TextGameScreenCenter.Instance.ShowText(TextGameScreenCenter.TextName.FLY_AWAY); //恢复箭 ResumeArrows(duck); } int exitDuckCount = 0; void HandleOnDuckExit(Duck duck) { if (duck.dead) Dog.Instance?.OnEvent(Dog.SensitiveEventType.DuckHit, duck); else { RemoveArrows(duck); GameUI.Instance.RenderHitDuckCount(0); Dog.Instance?.OnEvent(Dog.SensitiveEventType.DuckGetAway); } exitDuckCount++; } float _lastFallDownTime = 0; void HandleOnDuckFallDown(Duck duck) { _lastFallDownTime = Time.time; } [System.NonSerialized] public int hitCount = 0; private int bowHitCount = 0; void HandleOnHitDead(Duck duck) { hitCount++; int scoreToPlus = duck.config.type * 500; hitScore += scoreToPlus; GameUI.Instance.RenderHitDuckCount(duck.config.type); //射击状态下,刷新添加分数 if (bAddCountScore) { bowHitCount++; _CumulativeScore += scoreToPlus; uploadScore += scoreToPlus; //击杀野鸭分数 GameUI.Instance.RenderHitScore(_CumulativeScore, GetBestScore()); GameUI.Instance.ShowTextHitScore(scoreToPlus, duck.transform.position); } RemoveArrows(duck); } public void OnModuleRotationUpdate(Quaternion rotation) { CrossHair.Instance?.UpdatePositionByModuleRotation(rotation); } public void OnModuleShooting(float speed, bool bAddCount = false) { if (CrossHair.Instance) { if (isGamePlaying) { if (UseOneArrow(bAddCount)) { CrossHair.Instance.Shoot(); CheckShootPointHitDuck(); CheckNotifyFlyAway(); } } else if (!isGameStarted) { //CrossHair.Instance.Shoot(); if (GameUI.Instance.CheckHitDuckForGameStart(CrossHair.Instance.transform.position)) { OnClick_GameStart(); } } } } void CheckShootPointHitDuck() { bool hitDuck = false; Vector2 aimPos = CrossHair.Instance.transform.position; for (int i = Duck.DuckList.Count - 1; i >= 0; i--) { Duck duck = Duck.DuckList[i]; RectTransform duckRTF = duck.transform as RectTransform; bool intersect = RectTransformUtility.RectangleContainsScreenPoint(duckRTF, aimPos); bool hitFrontBG = false; Collider2D[] hitColliders = Physics2D.OverlapPointAll(aimPos); foreach (var item in hitColliders) { if (item.name.StartsWith("BGFront")) { hitFrontBG = true; break; } } if (intersect && !hitFrontBG && duck.Hit()) { hitDuck = true; break; } } if (!hitDuck) { GameUI.Instance.AddArrowOnScreen(aimPos); } else { //枪械模式下,射中也加个效果 if(GlobalData.MyDeviceMode == DeviceMode.Gun) { GameUI.Instance.AddArrowOnScreen(aimPos); } } } void OnClick_GameStart() { AudioManager.Instance.PlayGameStart(); StartGame(false); } void StartGame(bool startImmediate) { if (isGameStarted) return; isGameStarted = true; onGameStart?.Invoke(); GameUI.Instance.HandleGameStart(() => { dogSideObject.SetActive(true); dogSideObject.GetComponent().onExit = () => canCreateDuck = true; TextGameScreenCenter.Instance.ShowText(TextGameScreenCenter.TextName.ROUND_X, new object[] { level }); }, startImmediate); NoArrows(); GameUI.Instance.RenderLevel(level); // GameUI.Instance.RenderHitScore(hitScore, GetBestScore()); GameUI.Instance.RenderHitScore(_CumulativeScore, GetBestScore()); } void SettleGame() { if (isGameOver) return; if (_ductTypeList == null) return; if (Dog.Instance != null && Dog.Instance.isShowing) return; if (needCreateDuckCount != exitDuckCount) return; isGameOver = true; Debug.Log("Game Over"); GameUI.Instance.RenderHitDuckCount(-1); if (hitCount < passNeedHitCount) { //通关失败 TextGameScreenCenter.Instance.ShowText(TextGameScreenCenter.TextName.GAME_OVER, null, () => { UnityEngine.SceneManagement.SceneManager.LoadScene("DuckHunter"); }); AudioManager.Instance.PlayGameOver(); Debug.Log("通关失败"); } else { //完美通关 if (needCreateDuckCount == hitCount && needCreateDuckCount == bowHitCount) { //奖励额外积分 int plusScore = 10000; hitScore += plusScore; _CumulativeScore += plusScore; uploadScore += plusScore; GameUI.Instance.RenderHitScore(_CumulativeScore, GetBestScore()); TextGameScreenCenter.Instance.ShowText(TextGameScreenCenter.TextName.SUPER_ARCHER, new object[] { plusScore }, ShowGamePass); AudioManager.Instance.PlayFullScore(); } else { ShowGamePass(); } } //通过关卡时候,上传一次分数 onUploadScore(); SaveBestScore(); GameOverInterface.OnGameOver(GameMgr.gameType); } //野鸭退出时候保存分数到服务器 public void onUploadScore() { if (uploadScore > 0) { Debug.Log("野鸭上传的积分为:" + uploadScore); RankComp.Instance.uploadSinglePlayerGameRes(uploadScore); uploadScore = 0; } } void ShowGamePass() { //通关成功 TextGameScreenCenter.Instance.ShowText(TextGameScreenCenter.TextName.GAME_COMPLETED, null, () => { //自动进入下一关 if (level < 20) { DefaultLevel = level + 1; AutoNextLevel = true; } UnityEngine.SceneManagement.SceneManager.LoadScene("DuckHunter"); }); AudioManager.Instance.PlayGamePass(); Debug.Log("通关成功"); } int _arrowCount; int arrowCount { get { // int count = 0; // _duckCanShootCountList.ForEach(e => count += e.shootCount); // return count; return _arrowCount; } } List _duckCanShootCountList = new List(); class DuckCanShootCount { public Duck duck; public int shootCount; public DuckCanShootCount(Duck duck, int shootCount) { this.duck = duck; this.shootCount = shootCount; } } void ResumeArrows(Duck duck) { // _duckCanShootCountList.Add(new DuckCanShootCount(duck, 3)); _arrowCount = 3; GameUI.Instance.RenderArrowCount(arrowCount); } void RemoveArrows(Duck duck) { // _duckCanShootCountList.RemoveAll(e => e.duck == duck); // GameUI.Instance.RenderArrowCount(arrowCount); } bool UseOneArrow(bool bAddCount = false) { //根据射箭状态赋值 bAddCountScore = bAddCount; if (arrowCount > 0) { // foreach (var e in _duckCanShootCountList) // { // if (e.shootCount > 0) // { // e.shootCount--; // break; // } // } if (bAddCount) userGameAnalyse1.changeShootingCount(1); _arrowCount--; GameUI.Instance.RenderArrowCount(arrowCount); return true; } return false; } void NoArrows() { // _duckCanShootCountList = new List(); _arrowCount = 0; GameUI.Instance.RenderArrowCount(arrowCount); } void CheckNotifyFlyAway() { // foreach (var e in _duckCanShootCountList) // if (e.shootCount == 0) // e.duck.NotifyFlyAway(); if (arrowCount <= 0) foreach (var duck in Duck.DuckList) duck.NotifyFlyAway(); } //累计得分 private static int _CumulativeScore = 0; private static int _BestScoreVersion = 1; string GetBestScoreKey() { // return "BestScore_Level" + level + "_V" + _BestScoreVersion; return "DuckHunter_" + LoginMgr.myUserInfo.id + "_" + _BestScoreVersion; } void SaveBestScore() { string k = GetBestScoreKey(); int s = PlayerPrefs.GetInt(k, 0); // if (hitScore > s) PlayerPrefs.SetInt(k, hitScore); if (_CumulativeScore > s) PlayerPrefs.SetInt(k, _CumulativeScore); } int GetBestScore() { string k = GetBestScoreKey(); int s = PlayerPrefs.GetInt(k, 0); return s; } } }