GameFlowManager.ts 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. import { _decorator, Component, Node, resources, sp, Asset, Button } from 'cc';
  2. import { DataManager } from './DataManager';
  3. import { CharacterMovementManager } from './CharacterMovementManager';
  4. import { QuestionAnswerManager } from './QuestionAnswerManager';
  5. const { ccclass, property } = _decorator;
  6. @ccclass('GameFlowManager')
  7. export class GameFlowManager extends Component {
  8. @property({
  9. type: DataManager,
  10. tooltip: '数据管理器引用'
  11. })
  12. dataManager: DataManager = null;
  13. @property({
  14. type: CharacterMovementManager,
  15. tooltip: '人物移动管理器引用'
  16. })
  17. characterMovementManager: CharacterMovementManager = null;
  18. @property({
  19. type: QuestionAnswerManager,
  20. tooltip: '问答管理器引用'
  21. })
  22. questionAnswerManager: QuestionAnswerManager = null;
  23. @property({
  24. type: Node,
  25. tooltip: '角色显示节点(用于设置骨骼动画)'
  26. })
  27. characterSkeletonNode: Node = null;
  28. @property({
  29. type: Button,
  30. tooltip: '放行按钮'
  31. })
  32. allowButton: Button = null;
  33. @property({
  34. type: Button,
  35. tooltip: '赶走按钮'
  36. })
  37. dismissButton: Button = null;
  38. // 当前关卡中的NPC索引
  39. private currentNpcIndex: number = -1;
  40. // 当前关卡的NPC列表
  41. private currentNpcs: any[] = [];
  42. start() {
  43. // 注册按钮事件
  44. this.registerButtonEvents();
  45. // 开始游戏流程
  46. this.startGameFlow();
  47. }
  48. /**
  49. * 注册按钮事件
  50. */
  51. private registerButtonEvents(): void {
  52. // 注册放行按钮点击事件
  53. if (this.allowButton) {
  54. this.allowButton.node.on(Button.EventType.CLICK, this.handleCharacterPassed, this);
  55. } else {
  56. console.error('放行按钮未设置');
  57. }
  58. // 注册赶走按钮点击事件
  59. if (this.dismissButton) {
  60. this.dismissButton.node.on(Button.EventType.CLICK, this.handleCharacterDismissed, this);
  61. } else {
  62. console.error('赶走按钮未设置');
  63. }
  64. }
  65. /**
  66. * 开始游戏流程
  67. */
  68. private startGameFlow(): void {
  69. // 获取当前关卡数据
  70. const currentLevel = this.dataManager.getCurrentLevel();
  71. if (!currentLevel) {
  72. console.error('无法获取当前关卡数据');
  73. return;
  74. }
  75. console.log(`开始关卡: ${currentLevel.name}`);
  76. // 获取当前关卡的NPC列表
  77. this.currentNpcs = currentLevel.npcs;
  78. // 重置NPC索引
  79. this.currentNpcIndex = -1;
  80. // 显示第一个NPC
  81. this.showNextNpc();
  82. }
  83. /**
  84. * 显示下一个NPC
  85. */
  86. public showNextNpc(): void {
  87. console.log('showNextNpc');
  88. this.currentNpcIndex++;
  89. // 检查是否还有NPC
  90. if (this.currentNpcIndex >= this.currentNpcs.length) {
  91. console.log('当前关卡所有NPC已处理完毕');
  92. // 可以在这里添加关卡完成逻辑
  93. return;
  94. }
  95. // 获取当前NPC数据
  96. const npc = this.currentNpcs[this.currentNpcIndex];
  97. // 配置角色外观
  98. this.setupCharacterAppearance(npc.characterId, npc.skinName);
  99. // 配置问答对
  100. this.setupQuestionAnswers(npc.qaPairs);
  101. // 让角色入场
  102. this.characterMovementManager.characterEnter();
  103. }
  104. /**
  105. * 设置角色外观
  106. * @param characterId 角色ID
  107. * @param skinName 皮肤名称
  108. */
  109. private setupCharacterAppearance(characterId: number, skinName: string): void {
  110. if (!this.characterSkeletonNode) {
  111. console.error('角色骨骼节点未设置');
  112. return;
  113. }
  114. // 构建角色资源路径(左边补0确保两位数)
  115. const characterFolderName = characterId < 10 ? `0${characterId}` : `${characterId}`;
  116. const characterPath = `${characterFolderName}`;
  117. // 加载角色骨骼动画资源
  118. resources.load(`${characterPath}/${characterId}`, sp.SkeletonData, (err, skeletonData) => {
  119. if (err) {
  120. console.error(`加载角色资源失败: ${characterPath}/${characterId}`, err);
  121. return;
  122. }
  123. // 获取骨骼动画组件
  124. const skeletonComponent = this.characterSkeletonNode.getComponent(sp.Skeleton);
  125. if (skeletonComponent) {
  126. // 设置骨骼数据
  127. skeletonComponent.skeletonData = skeletonData;
  128. skeletonComponent.setSkin(skinName);
  129. skeletonComponent.setAnimation(0, 'loop', true);
  130. console.log(`设置角色: ${characterId}, 皮肤: ${skinName}`);
  131. } else {
  132. console.error('角色节点上没有sp.Skeleton组件');
  133. }
  134. });
  135. }
  136. /**
  137. * 设置问答对
  138. * @param qaPairs 问答对数组
  139. */
  140. private setupQuestionAnswers(qaPairs: any[]): void {
  141. if (!this.questionAnswerManager) {
  142. console.error('问答管理器未设置');
  143. return;
  144. }
  145. // 替换所有问答对(而不是添加)
  146. this.questionAnswerManager.replaceAllQuestionAnswers(qaPairs);
  147. }
  148. /**
  149. * 处理放行角色
  150. */
  151. public handleCharacterPassed(): void {
  152. // 让角色向右移动
  153. this.characterMovementManager.moveCharacterRight();
  154. // 延迟显示下一个NPC
  155. this.scheduleOnce(() => {
  156. this.showNextNpc();
  157. }, this.characterMovementManager.moveDuration + 0.5);
  158. }
  159. /**
  160. * 处理赶走角色
  161. */
  162. public handleCharacterDismissed(): void {
  163. // 让角色向左移动
  164. this.characterMovementManager.moveCharacterLeft();
  165. // 延迟显示下一个NPC
  166. this.scheduleOnce(() => {
  167. this.showNextNpc();
  168. }, this.characterMovementManager.moveDuration + 0.5);
  169. }
  170. /**
  171. * 组件销毁时清理事件监听
  172. */
  173. onDestroy() {
  174. // 移除按钮事件监听
  175. if (this.allowButton) {
  176. this.allowButton.node.off(Button.EventType.CLICK, this.handleCharacterPassed, this);
  177. }
  178. if (this.dismissButton) {
  179. this.dismissButton.node.off(Button.EventType.CLICK, this.handleCharacterDismissed, this);
  180. }
  181. }
  182. }