StoryM.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using DG.Tweening;
  4. using UnityEngine;
  5. using UnityEngine.Localization.Settings;
  6. using UnityEngine.UI;
  7. using System.Linq;
  8. public class StoryM : MonoBehaviour {
  9. // 文本
  10. public TMPro.TextMeshProUGUI textStory;
  11. public RectTransform shapeBack;
  12. /// <summary>
  13. /// 设置旁白,并返回预期时间。旁白字幕将在预期时间后消失。
  14. /// </summary>
  15. public float SetStoryText(string textCn, string textEn = "English") {
  16. bool isCn = LocalizationSettings.SelectedLocale.LocaleName == "Chinese (Simplified) (zh-CN)";
  17. textStory.text = isCn ? textCn : textEn;
  18. LayoutRebuilder.ForceRebuildLayoutImmediate(textStory.rectTransform);
  19. // 动画
  20. textStory.color = Color.black;
  21. DOTween.Kill("StoryFont"); textStory.DOColor(Color.white, 0.25f).SetId("StoryFont");
  22. DOTween.Kill("StoryBackground"); shapeBack.DOScaleX((textStory.rectTransform.rect.width + 40f) / 100f, 0.15f).SetId("StoryBackground");
  23. // 消失
  24. float time = 1f + (isCn ? textCn.Length / 4f : textEn.Split(" ").Length / 4f);
  25. StopCoroutine("WaitForHideStoryText"); StartCoroutine("WaitForHideStoryText", time);
  26. Debug.Log(time + " -> " + textCn);
  27. return time;
  28. }
  29. IEnumerator WaitForStoryText(string textCh, string textEn = "English") {
  30. yield return new WaitForSeconds(SetStoryText(textCh, textEn));
  31. }
  32. IEnumerator WaitForHideStoryText(float delay) {
  33. yield return new WaitForSeconds(delay);
  34. Debug.Log("隐藏:" + delay);
  35. HideStoryText();
  36. }
  37. void HideStoryText() {
  38. StopCoroutine("WaitForHideStoryText");
  39. textStory.text = "";
  40. DOTween.Kill("StoryBackground"); shapeBack.DOScaleX(0, 0.2f).SetId("StoryBackground");
  41. }
  42. // 刷怪
  43. private Dictionary<Spawner.EnemyType, List<Spawner>> spawners = null;
  44. public void Spawn(Spawner.EnemyType type, int count = 1) {
  45. // 初始化
  46. if (spawners == null) {
  47. spawners = new();
  48. foreach (Spawner spawner in FindObjectsOfType<Spawner>()) {
  49. if (spawners.ContainsKey(spawner.type)) {
  50. spawners[spawner.type].Add(spawner);
  51. } else {
  52. spawners[spawner.type] = new() { spawner };
  53. }
  54. }
  55. }
  56. // 实际刷怪
  57. spawners[type].Shuffle();
  58. for (int i = 0; i < count; i++) {
  59. if (i >= spawners[type].Count) i = 0;
  60. spawners[type][i].Spawn();
  61. }
  62. }
  63. // 流程控制
  64. IEnumerator WaitUntilClear(int remain, float waitTime = -1, string textCn = "", string textEn = "") {
  65. while (GetEnemyCount() > remain && !respawning) {
  66. if (waitTime >= 0f && waitTime < 0.3f) SetStoryText(textCn, textEn);
  67. waitTime -= 0.3f;
  68. yield return new WaitForSeconds(0.3f);
  69. }
  70. }
  71. int GetEnemyCount() => FindObjectsOfType<EnemyBase>().Length - FindObjectsOfType<EnemyArrow>().Length;
  72. IEnumerator WaitUntilPickDice(float waitTime = -1, string textCn = "", string textEn = "") {
  73. while (GetDiceCount() > 0 && !respawning) {
  74. if (waitTime >= 0f && waitTime < 0.3f) SetStoryText(textCn, textEn);
  75. waitTime -= 0.3f;
  76. yield return new WaitForSeconds(0.3f);
  77. }
  78. }
  79. int GetDiceCount() => FindObjectsOfType<DiceEntity>().Count(dice => !dice.pickedUp);
  80. // 故事
  81. public int stage = 0; private bool stageCompleted = true;
  82. public Image panDeath;
  83. void Start() {
  84. StartCoroutine("ArrowSpawner");
  85. StartCoroutine("Main");
  86. }
  87. IEnumerator Main() {
  88. while (true) {
  89. if (Input.GetKey(KeyCode.LeftControl) && Input.GetKeyUp(KeyCode.Q)) {
  90. SetStoryText("已跳过阶段:" + stage, "Skip Stage: " + stage);
  91. stageCompleted = true;
  92. }
  93. if (Player.hp <= 0) {
  94. stageCompleted = false;
  95. yield return StartCoroutine("Respawn");
  96. }
  97. if (stageCompleted) {
  98. deathInStage = 0;
  99. stageCompleted = false;
  100. StopCoroutine("Stage" + stage);
  101. stage++;
  102. Debug.Log("已到达阶段:" + stage);
  103. StartCoroutine("Stage" + stage);
  104. }
  105. yield return new WaitForFixedUpdate();
  106. }
  107. }
  108. private int deathInStage = 0; private bool respawning = false, noDifficulty = false;
  109. IEnumerator Respawn() {
  110. deathInStage++; respawning = true;
  111. // 停止场景
  112. arrowMax = 0;
  113. Player.instance.transform.localScale = Vector3.zero;
  114. Player.instance.GetComponent<Rigidbody2D>().velocity = Vector2.zero;
  115. Player.instance.enabled = false;
  116. StopCoroutine("Stage" + stage);
  117. StopCoroutine("HideStoryText");
  118. yield return new WaitForSeconds(1.5f);
  119. if (!noDifficulty) {
  120. _ = Modules.randomDefault.Next(0, 3) switch {
  121. 0 => SetStoryText("完了,寄咯!", ""),
  122. 1 => SetStoryText("哦吼,下次加油吧", ""),
  123. 2 => SetStoryText("诶,怎么回事?", ""),
  124. 3 => SetStoryText("还好没开极限模式……", ""),
  125. _ => throw new System.NotImplementedException(),
  126. };
  127. } else {
  128. _ = Modules.randomDefault.Next(0, 2) switch {
  129. 0 => SetStoryText("不是吧?这也能死?", ""),
  130. 1 => SetStoryText("你是特么故意的吧!", ""),
  131. 2 => SetStoryText("哈?", ""),
  132. _ => throw new System.NotImplementedException(),
  133. };
  134. }
  135. yield return new WaitForSeconds(0.5f);
  136. // 转为黑屏
  137. panDeath.DOFade(1, 0.3f); panDeath.GetComponentInChildren<TMPro.TextMeshProUGUI>().DOFade(1, 1f);
  138. yield return new WaitForSeconds(0.3f);
  139. // 复原
  140. FindObjectsOfType<EnemyBase>().ToList().ForEach(e => GameObject.Destroy(e.gameObject, 1f));
  141. Player.hp = 3;
  142. Player.instance.currentBullet = Player.instance.maxBullet;
  143. yield return new WaitForSeconds(3f);
  144. // 淡出黑屏,玩家重生
  145. respawning = false;
  146. panDeath.DOFade(0, 0.8f); panDeath.GetComponentInChildren<TMPro.TextMeshProUGUI>().DOFade(0, 0.3f);
  147. Player.instance.enabled = true;
  148. Player.instance.transform.localScale = Vector3.one;
  149. Player.instance.transform.position = new Vector3(-6, 10, 0);
  150. // 继续游戏
  151. yield return new WaitForSeconds(2f);
  152. StartCoroutine("Stage" + stage);
  153. }
  154. IEnumerator Stage1() {
  155. arrowMax = 0; noDifficulty = false;
  156. yield return new WaitForSeconds(3f);
  157. yield return StartCoroutine(WaitForStoryText("哦,哦!你好,欢迎欢迎", ""));
  158. yield return StartCoroutine(WaitForStoryText("先来过个教程啥的吧", ""));
  159. yield return StartCoroutine(WaitForStoryText("游戏的按键操作写在了右上角,应该是个人都看得懂", ""));
  160. SetStoryText("你不如先拿它们俩试试按键吧!", "");
  161. Spawn(Spawner.EnemyType.Mover, 2);
  162. yield return StartCoroutine(WaitUntilClear(0, 10f, "快点把它干掉,然后才好继续……", ""));
  163. stageCompleted = true;
  164. }
  165. IEnumerator Stage2() {
  166. arrowMax = 1; noDifficulty = false;
  167. Spawn(Spawner.EnemyType.Mover, 2);
  168. yield return StartCoroutine(WaitForStoryText("哦,教程最后一条……", ""));
  169. Spawn(Spawner.EnemyType.Mover, 2);
  170. yield return StartCoroutine(WaitForStoryText("弹药不够的时候记得换弹", ""));
  171. Spawn(Spawner.EnemyType.Shooter, 1);
  172. SetStoryText("加油,教程结束了!", "");
  173. yield return StartCoroutine(WaitUntilClear(1, 10f, "仔细一看,这个角色的手上连枪都没有……", ""));
  174. if (Player.hp < 3) {
  175. Player.hp = 3;
  176. Spawn(Spawner.EnemyType.Mover, 1);
  177. yield return StartCoroutine(WaitForStoryText("对了,教程结束得先给你回个血……", ""));
  178. }
  179. stageCompleted = true;
  180. }
  181. IEnumerator Stage3() {
  182. arrowMax = 3; noDifficulty = false;
  183. Spawn(Spawner.EnemyType.Mover, 1);
  184. yield return StartCoroutine(WaitForStoryText("说实话啊,我觉得这个游戏有点无聊", ""));
  185. Spawn(Spawner.EnemyType.Mover, 1);
  186. yield return StartCoroutine(WaitForStoryText("我看了看,这游戏往后的新内容就只剩一种换皮怪了!", ""));
  187. Spawn(Spawner.EnemyType.Mover, 1);
  188. yield return StartCoroutine(WaitForStoryText("然后就是“在无限的怪物中生存下来吧!”的无尽模式……", ""));
  189. Spawn(Spawner.EnemyType.Mover, 1);
  190. yield return StartCoroutine(WaitForStoryText("没有升级,没有装备,没有峰回路转的牛逼剧情", ""));
  191. Spawn(Spawner.EnemyType.Shooter, 1);
  192. yield return StartCoroutine(WaitForStoryText("并且最重要的是,“丢骰子”的主题呢?", ""));
  193. yield return StartCoroutine(WaitForStoryText("骰子、骰子……哪儿有骰子……?", ""));
  194. arrowMax = 0;
  195. Spawn(Spawner.EnemyType.Mover, 1);
  196. yield return StartCoroutine(WaitUntilClear(0, 8f, "这里一个骰子都没有!切题呢?作者到底咋想的?", ""));
  197. noDifficulty = true;
  198. yield return StartCoroutine(WaitForStoryText("要不然这样,我们随便拿个东西,把它弄成骰子算了", ""));
  199. yield return new WaitForSeconds(2f);
  200. InputM.DropDice(InputM.KeyType.Fire);
  201. SetStoryText("嘿,成了!", "");
  202. stageCompleted = true;
  203. }
  204. IEnumerator Stage4() {
  205. arrowMax = 0; noDifficulty = true;
  206. yield return StartCoroutine(WaitUntilPickDice(10f, "看到右边掉下来的东西了么?把它捡起来摇一摇!", ""));
  207. stageCompleted = true;
  208. }
  209. IEnumerator Stage5() {
  210. arrowMax = 0; noDifficulty = true;
  211. yield return new WaitForSeconds(1.5f);
  212. yield return StartCoroutine(WaitForStoryText("噔噔噔……!", ""));
  213. yield return new WaitForSeconds(6f);
  214. yield return StartCoroutine(WaitForStoryText("你看,这就是天才制作的骰子", ""));
  215. yield return new WaitForSeconds(1.5f);
  216. Spawn(Spawner.EnemyType.Mover, 1);
  217. if (Player.hp < 3) {
  218. Player.hp = 3;
  219. yield return StartCoroutine(WaitForStoryText("让我帮你回个血,我们继续!", ""));
  220. } else {
  221. yield return StartCoroutine(WaitForStoryText("来,我们继续!", ""));
  222. }
  223. stageCompleted = true;
  224. }
  225. IEnumerator Stage6() {
  226. arrowMax = 1; noDifficulty = false;
  227. Spawn(Spawner.EnemyType.Mover, 3);
  228. yield return new WaitForSeconds(1.5f);
  229. }
  230. //IEnumerator test() {
  231. // while (true) {
  232. // Spawn(Spawner.EnemyType.Mover, 3);
  233. // SetStoryText("先刷几个瞎晃悠的", "");
  234. // yield return new WaitForSeconds(3f);
  235. // Spawn(Spawner.EnemyType.Shooter);
  236. // SetStoryText("炮塔!", "");
  237. // yield return new WaitForSeconds(2f);
  238. // Spawn(Spawner.EnemyType.Heavy, 2);
  239. // SetStoryText("最后是两个贼硬的……", "");
  240. // yield return StartCoroutine(WaitUntilClear(2));
  241. // InputM.DropDice(Modules.RandomOne(InputM.keyTypes.ToList()));
  242. // SetStoryText("来一个骰子吧……?", "");
  243. // yield return StartCoroutine(WaitUntilPickDice());
  244. // yield return StartCoroutine(WaitForStoryText("准备好,下一轮要来了!", ""));
  245. // }
  246. //}
  247. int arrowMax = 0; float arrowTime = 4f;
  248. IEnumerator ArrowSpawner() {
  249. while (true) {
  250. yield return new WaitForSeconds(arrowTime);
  251. if (arrowMax > 0) Spawn(Spawner.EnemyType.Arrow, Modules.randomDefault.Next(0, arrowMax));
  252. }
  253. }
  254. }