StoryM.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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. textStory.text = "";
  35. Debug.Log(delay);
  36. DOTween.Kill("StoryBackground"); shapeBack.DOScaleX(0, 0.2f).SetId("StoryBackground");
  37. }
  38. // 刷怪
  39. private Dictionary<Spawner.EnemyType, List<Spawner>> spawners = null;
  40. public void Spawn(Spawner.EnemyType type, int count = 1) {
  41. // 初始化
  42. if (spawners == null) {
  43. spawners = new();
  44. foreach (Spawner spawner in FindObjectsOfType<Spawner>()) {
  45. if (spawners.ContainsKey(spawner.type)) {
  46. spawners[spawner.type].Add(spawner);
  47. } else {
  48. spawners[spawner.type] = new() { spawner };
  49. }
  50. }
  51. }
  52. // 实际刷怪
  53. spawners[type].Shuffle();
  54. for (int i = 0; i < count; i++) {
  55. if (i >= spawners[type].Count) i = 0;
  56. spawners[type][i].Spawn();
  57. }
  58. }
  59. // 流程控制
  60. IEnumerator WaitUntilClear(int remain, float waitTime = -1, string textCn = "", string textEn = "") {
  61. while (GetEnemyCount() > remain) { // 要算上自己
  62. if (waitTime >= 0f && waitTime < 0.3f) { // 触发额外对话
  63. SetStoryText(textCn, textEn);
  64. }
  65. waitTime -= 0.3f;
  66. yield return new WaitForSeconds(0.3f);
  67. }
  68. }
  69. int GetEnemyCount() => FindObjectsOfType<EnemyBase>().Length - FindObjectsOfType<EnemyArrow>().Length;
  70. IEnumerator WaitUntilPickDice(float waitTime = -1, string textCn = "", string textEn = "") {
  71. while (GetDiceCount() > 0) {
  72. if (waitTime >= 0f && waitTime < 0.3f) { // 触发额外对话
  73. SetStoryText(textCn, textEn);
  74. }
  75. waitTime -= 0.3f;
  76. yield return new WaitForSeconds(0.3f);
  77. }
  78. }
  79. int GetDiceCount() => FindObjectsOfType<DiceEntity>().Length;
  80. // 故事
  81. public int stage = 0; private bool stageCompleted = true;
  82. void Start() {
  83. StartCoroutine("ArrowSpawner");
  84. StartCoroutine("Main");
  85. }
  86. IEnumerator Main() {
  87. while (true) {
  88. if (Input.GetKey(KeyCode.LeftControl) && Input.GetKeyUp(KeyCode.Q)) {
  89. SetStoryText("已跳过阶段:" + stage, "Skip Stage: " + stage);
  90. stageCompleted = true;
  91. }
  92. if (stageCompleted) {
  93. stageCompleted = false;
  94. StopCoroutine("Stage" + stage);
  95. stage++;
  96. StartCoroutine("Stage" + stage);
  97. }
  98. yield return new WaitForFixedUpdate();
  99. }
  100. }
  101. IEnumerator Stage1() {
  102. arrowMax = 0;
  103. yield return new WaitForSeconds(3f);
  104. yield return StartCoroutine(WaitForStoryText("哦,哦!你好,欢迎欢迎", ""));
  105. yield return StartCoroutine(WaitForStoryText("先来过个教程啥的吧", ""));
  106. yield return StartCoroutine(WaitForStoryText("游戏的按键操作写在了右上角,应该是个人都看得懂", ""));
  107. SetStoryText("你不如先拿它们俩试试按键吧!", "");
  108. Spawn(Spawner.EnemyType.Mover, 2);
  109. yield return StartCoroutine(WaitUntilClear(0, 10f, "快点把它干掉,然后才好继续……", ""));
  110. stageCompleted = true;
  111. }
  112. IEnumerator Stage2() {
  113. arrowMax = 1;
  114. Spawn(Spawner.EnemyType.Mover, 2);
  115. yield return StartCoroutine(WaitForStoryText("哦,教程最后一条……", ""));
  116. Spawn(Spawner.EnemyType.Mover, 2);
  117. yield return StartCoroutine(WaitForStoryText("弹药不够的时候记得换弹", ""));
  118. Spawn(Spawner.EnemyType.Shooter, 1);
  119. SetStoryText("加油,教程结束了!", "");
  120. yield return StartCoroutine(WaitUntilClear(1, 10f, "仔细一看,这个角色的手上连枪都没有……", ""));
  121. if (Player.hp < 3) {
  122. Player.hp = 3;
  123. Spawn(Spawner.EnemyType.Mover, 1);
  124. yield return StartCoroutine(WaitForStoryText("对了,教程结束得先给你回个血……", ""));
  125. }
  126. stageCompleted = true;
  127. }
  128. IEnumerator Stage3() {
  129. arrowMax = 3;
  130. Spawn(Spawner.EnemyType.Mover, 1);
  131. yield return StartCoroutine(WaitForStoryText("说实话啊,我觉得这个游戏有点无聊", ""));
  132. Spawn(Spawner.EnemyType.Mover, 1);
  133. yield return StartCoroutine(WaitForStoryText("我看了看,这游戏往后的新内容就只剩一种换皮怪了!", ""));
  134. Spawn(Spawner.EnemyType.Mover, 1);
  135. yield return StartCoroutine(WaitForStoryText("然后就是“在无限的怪物中生存下来吧!”的无尽模式……", ""));
  136. Spawn(Spawner.EnemyType.Mover, 1);
  137. yield return StartCoroutine(WaitForStoryText("没有升级,没有装备,没有峰回路转的牛逼剧情", ""));
  138. Spawn(Spawner.EnemyType.Shooter, 1);
  139. yield return StartCoroutine(WaitForStoryText("并且最重要的是,“丢骰子”的主题呢?", ""));
  140. yield return StartCoroutine(WaitForStoryText("骰子、骰子……哪儿有骰子……?", ""));
  141. arrowMax = 0;
  142. Spawn(Spawner.EnemyType.Mover, 1);
  143. yield return StartCoroutine(WaitUntilClear(0, 6f, "这里一个骰子都没有!切题呢?作者到底咋想的?", ""));
  144. stageCompleted = true;
  145. }
  146. IEnumerator Stage4() {
  147. arrowMax = 0;
  148. Player.hp = 3;
  149. yield return StartCoroutine(WaitForStoryText("要不然这样,我们随便拿个东西,把它弄成骰子算了", ""));
  150. yield return new WaitForSeconds(2f);
  151. if (GetDiceCount() == 0) {
  152. InputM.DropDice(InputM.KeyType.Fire);
  153. SetStoryText("嘿,成了!", "");
  154. }
  155. yield return StartCoroutine(WaitUntilPickDice(5f, "看到右边掉下来的东西了么?把它捡起来摇一摇!", ""));
  156. yield return new WaitForSeconds(2f);
  157. yield return StartCoroutine(WaitForStoryText("你看,完美!", ""));
  158. stageCompleted = true;
  159. }
  160. IEnumerator Stage5() {
  161. yield return new WaitForSeconds(2f);
  162. }
  163. //IEnumerator test() {
  164. // while (true) {
  165. // Spawn(Spawner.EnemyType.Mover, 3);
  166. // SetStoryText("先刷几个瞎晃悠的", "");
  167. // yield return new WaitForSeconds(3f);
  168. // Spawn(Spawner.EnemyType.Shooter);
  169. // SetStoryText("炮塔!", "");
  170. // yield return new WaitForSeconds(2f);
  171. // Spawn(Spawner.EnemyType.Heavy, 2);
  172. // SetStoryText("最后是两个贼硬的……", "");
  173. // yield return StartCoroutine(WaitUntilClear(2));
  174. // InputM.DropDice(Modules.RandomOne(InputM.keyTypes.ToList()));
  175. // SetStoryText("来一个骰子吧……?", "");
  176. // yield return StartCoroutine(WaitUntilPickDice());
  177. // yield return StartCoroutine(WaitForStoryText("准备好,下一轮要来了!", ""));
  178. // }
  179. //}
  180. int arrowMax = 0; float arrowTime = 4f;
  181. IEnumerator ArrowSpawner() {
  182. while (true) {
  183. yield return new WaitForSeconds(arrowTime);
  184. if (arrowMax > 0) Spawn(Spawner.EnemyType.Arrow, Modules.randomDefault.Next(0, arrowMax));
  185. }
  186. }
  187. }