SummaryManager.ts 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  1. import { _decorator, Component, Node, Label, Button, Sprite, SpriteFrame, resources, instantiate, UIOpacity, Widget, UITransform, director, Canvas, AssetManager } from 'cc';
  2. import { DataManager } from './DataManager';
  3. import { GameFlowManager } from './GameFlowManager';
  4. const { ccclass, property } = _decorator;
  5. // 定义UI详情数据接口
  6. interface DetailItemData {
  7. name: string;
  8. avatarPath: string;
  9. characterId: number;
  10. }
  11. // 定义统计结果类型
  12. interface GameStats {
  13. passedRealCount: number; // 放行的邻居数量
  14. dismissedFakeCount: number; // 驱赶的伪人数量
  15. passedFakeCount: number; // 放行的伪人数量
  16. dismissedRealCount: number; // 驱赶的邻居数量
  17. passedRealList: DetailItemData[]; // 放行的邻居列表
  18. dismissedFakeList: DetailItemData[]; // 驱赶的伪人列表
  19. passedFakeList: DetailItemData[]; // 放行的伪人列表
  20. dismissedRealList: DetailItemData[]; // 驱赶的邻居列表
  21. grade: string; // 评分:A/B/C/D
  22. }
  23. @ccclass('SummaryManager')
  24. export class SummaryManager extends Component {
  25. @property({
  26. type: Node,
  27. tooltip: '总结面板节点'
  28. })
  29. summaryPanel: Node = null;
  30. @property({
  31. type: Label,
  32. tooltip: '放行邻居数量文本'
  33. })
  34. passedRealCountLabel: Label = null;
  35. @property({
  36. type: Label,
  37. tooltip: '驱赶伪人数量文本'
  38. })
  39. dismissedFakeCountLabel: Label = null;
  40. @property({
  41. type: Label,
  42. tooltip: '放行伪人数量文本'
  43. })
  44. passedFakeCountLabel: Label = null;
  45. @property({
  46. type: Label,
  47. tooltip: '驱赶邻居数量文本'
  48. })
  49. dismissedRealCountLabel: Label = null;
  50. @property({
  51. type: Label,
  52. tooltip: '等级评分文本'
  53. })
  54. gradeLabel: Label = null;
  55. @property({
  56. type: Button,
  57. tooltip: '查看放行伪人详情按钮'
  58. })
  59. viewPassedFakeButton: Button = null;
  60. @property({
  61. type: Button,
  62. tooltip: '查看驱赶邻居详情按钮'
  63. })
  64. viewDismissedRealButton: Button = null;
  65. @property({
  66. type: Node,
  67. tooltip: '详情面板节点'
  68. })
  69. detailPanel: Node = null;
  70. @property({
  71. type: Label,
  72. tooltip: '详情面板标题'
  73. })
  74. detailTitleLabel: Label = null;
  75. @property({
  76. type: Node,
  77. tooltip: '详情内容容器节点'
  78. })
  79. detailContentContainer: Node = null;
  80. @property({
  81. type: Node,
  82. tooltip: '详情条目预制体'
  83. })
  84. detailItemPrefab: Node = null;
  85. @property({
  86. type: Button,
  87. tooltip: '详情面板关闭按钮'
  88. })
  89. detailCloseButton: Button = null;
  90. @property({
  91. type: Node,
  92. tooltip: '角色详情面板'
  93. })
  94. characterDetailPanel: Node = null;
  95. @property({
  96. type: DataManager,
  97. tooltip: '数据管理器引用'
  98. })
  99. dataManager: DataManager = null;
  100. @property({
  101. type: Button,
  102. tooltip: '确认按钮'
  103. })
  104. confirmButton: Button = null;
  105. @property({
  106. type: GameFlowManager,
  107. tooltip: '游戏流程管理器引用'
  108. })
  109. gameFlowManager: GameFlowManager = null;
  110. // 游戏统计数据
  111. private gameStats: GameStats = {
  112. passedRealCount: 0,
  113. dismissedFakeCount: 0,
  114. passedFakeCount: 0,
  115. dismissedRealCount: 0,
  116. passedRealList: [],
  117. dismissedFakeList: [],
  118. passedFakeList: [],
  119. dismissedRealList: [],
  120. grade: 'D'
  121. };
  122. // 当前显示的详情类型
  123. private currentDetailType: 'passedFake' | 'dismissedReal' = null;
  124. // 在SummaryManager中添加回调属性
  125. public onShowCharacterDetail: (characterId: number) => void = null;
  126. // 添加初始化标记
  127. private isInitialized: boolean = false;
  128. // 添加标记表示是否正在显示总结面板
  129. private isShowingSummary: boolean = false;
  130. start() {
  131. console.log('SummaryManager.start被调用');
  132. // 避免重复初始化
  133. if (this.isInitialized) {
  134. console.log('SummaryManager已经初始化过,跳过初始化流程');
  135. return;
  136. }
  137. // 如果正在显示总结面板,跳过隐藏面板的步骤
  138. if (this.isShowingSummary) {
  139. console.log('总结面板正在显示中,跳过隐藏面板的初始化步骤');
  140. this.isInitialized = true;
  141. this.setupButtons();
  142. return;
  143. }
  144. // 检查面板引用
  145. if (!this.summaryPanel) {
  146. console.error('summaryPanel未被赋值,请检查Inspector中的引用设置');
  147. } else {
  148. console.log('summaryPanel初始状态:', this.summaryPanel.active);
  149. // 初始化隐藏面板,但先记录下它的初始状态以便调试
  150. this.summaryPanel.active = false;
  151. console.log('summaryPanel已设置为隐藏');
  152. }
  153. if (!this.detailPanel) {
  154. console.error('detailPanel未被赋值,请检查Inspector中的引用设置');
  155. } else {
  156. console.log('detailPanel初始状态:', this.detailPanel.active);
  157. this.detailPanel.active = false;
  158. console.log('detailPanel已设置为隐藏');
  159. }
  160. if (!this.characterDetailPanel) {
  161. console.error('characterDetailPanel未被赋值,请检查Inspector中的引用设置');
  162. } else {
  163. console.log('characterDetailPanel初始状态:', this.characterDetailPanel.active);
  164. this.characterDetailPanel.active = false;
  165. console.log('characterDetailPanel已设置为隐藏');
  166. }
  167. // 注册按钮事件
  168. this.setupButtons();
  169. // 标记为已初始化
  170. this.isInitialized = true;
  171. }
  172. /**
  173. * 设置按钮事件
  174. */
  175. private setupButtons(): void {
  176. // 查看放行伪人详情按钮
  177. if (this.viewPassedFakeButton) {
  178. this.viewPassedFakeButton.node.on(Button.EventType.CLICK, () => {
  179. this.showDetailPanel('passedFake');
  180. }, this);
  181. }
  182. // 查看驱赶邻居详情按钮
  183. if (this.viewDismissedRealButton) {
  184. this.viewDismissedRealButton.node.on(Button.EventType.CLICK, () => {
  185. this.showDetailPanel('dismissedReal');
  186. }, this);
  187. }
  188. // 详情面板关闭按钮
  189. if (this.detailCloseButton) {
  190. this.detailCloseButton.node.on(Button.EventType.CLICK, () => {
  191. this.hideDetailPanel();
  192. }, this);
  193. }
  194. // 确认按钮
  195. if (this.confirmButton) {
  196. this.confirmButton.node.on(Button.EventType.CLICK, this.handleConfirmButtonClick, this);
  197. } else {
  198. console.error('确认按钮未设置');
  199. }
  200. }
  201. /**
  202. * 记录放行NPC
  203. * @param npcData NPC数据
  204. */
  205. public recordPassedNPC(npcData: any): void {
  206. if (!npcData) return;
  207. console.log(`记录放行NPC: ${npcData.characterName}, 类型: ${npcData.type}, ID: ${npcData.characterId}`);
  208. const detailData: DetailItemData = {
  209. name: npcData.characterName,
  210. avatarPath: `avatars/${npcData.characterId}/avatar_${npcData.characterId}_5`,
  211. characterId: npcData.characterId
  212. };
  213. if (npcData.type === 'real') {
  214. // 放行了邻居
  215. this.gameStats.passedRealCount++;
  216. this.gameStats.passedRealList.push(detailData);
  217. console.log(`放行邻居数量增加到 ${this.gameStats.passedRealCount}`);
  218. } else if (npcData.type === 'fake') {
  219. // 放行了伪人
  220. this.gameStats.passedFakeCount++;
  221. this.gameStats.passedFakeList.push(detailData);
  222. console.log(`放行伪人数量增加到 ${this.gameStats.passedFakeCount}`);
  223. }
  224. // 更新评分
  225. this.updateGrade();
  226. }
  227. /**
  228. * 记录驱赶NPC
  229. * @param npcData NPC数据
  230. */
  231. public recordDismissedNPC(npcData: any): void {
  232. if (!npcData) return;
  233. console.log(`记录驱赶NPC: ${npcData.characterName}, 类型: ${npcData.type}, ID: ${npcData.characterId}`);
  234. const detailData: DetailItemData = {
  235. name: npcData.characterName,
  236. avatarPath: `avatars/${npcData.characterId}/avatar_${npcData.characterId}_5`,
  237. characterId: npcData.characterId
  238. };
  239. if (npcData.type === 'real') {
  240. // 驱赶了邻居
  241. this.gameStats.dismissedRealCount++;
  242. this.gameStats.dismissedRealList.push(detailData);
  243. console.log(`驱赶邻居数量增加到 ${this.gameStats.dismissedRealCount}`);
  244. } else if (npcData.type === 'fake') {
  245. // 驱赶了伪人
  246. this.gameStats.dismissedFakeCount++;
  247. this.gameStats.dismissedFakeList.push(detailData);
  248. console.log(`驱赶伪人数量增加到 ${this.gameStats.dismissedFakeCount}`);
  249. }
  250. // 更新评分
  251. this.updateGrade();
  252. }
  253. /**
  254. * 更新评分
  255. */
  256. private updateGrade(): void {
  257. // 计算正确决策的百分比
  258. const totalDecisions = this.gameStats.passedRealCount + this.gameStats.dismissedFakeCount +
  259. this.gameStats.passedFakeCount + this.gameStats.dismissedRealCount;
  260. if (totalDecisions === 0) {
  261. this.gameStats.grade = 'D';
  262. return;
  263. }
  264. const correctDecisions = this.gameStats.passedRealCount + this.gameStats.dismissedFakeCount;
  265. const correctPercentage = (correctDecisions / totalDecisions) * 100;
  266. // 根据正确率确定等级
  267. if (correctPercentage >= 90) {
  268. this.gameStats.grade = 'A';
  269. } else if (correctPercentage >= 70) {
  270. this.gameStats.grade = 'B';
  271. } else if (correctPercentage >= 50) {
  272. this.gameStats.grade = 'C';
  273. } else {
  274. this.gameStats.grade = 'D';
  275. }
  276. }
  277. /**
  278. * 显示总结面板
  279. */
  280. public showSummaryPanel(): void {
  281. console.log('SummaryManager.showSummaryPanel被调用');
  282. // 尝试检查资源路径
  283. this.checkAvatarResources();
  284. // 标记为正在显示总结面板
  285. this.isShowingSummary = true;
  286. // 确保已初始化
  287. if (!this.isInitialized) {
  288. console.log('SummaryManager未初始化,执行初始化');
  289. this.isInitialized = true; // 标记为已初始化,避免start中再次隐藏面板
  290. }
  291. if (!this.summaryPanel) {
  292. console.error('summaryPanel未设置');
  293. return;
  294. }
  295. // 检查summaryPanel的父节点状态
  296. const parentNode = this.summaryPanel.parent;
  297. if (parentNode) {
  298. console.log('summaryPanel父节点状态:', parentNode.name, '激活状态:', parentNode.active);
  299. // 确保父节点也是激活的
  300. if (!parentNode.active) {
  301. console.log('激活summaryPanel的父节点');
  302. parentNode.active = true;
  303. }
  304. } else {
  305. console.error('summaryPanel没有父节点');
  306. }
  307. // 强制设置可见性相关属性
  308. this.summaryPanel.active = true;
  309. // 确保位于最顶层
  310. this.summaryPanel.setSiblingIndex(999);
  311. // 尝试强制将面板移动到场景顶层
  312. this.forceMoveToTop();
  313. // 如果节点有UIOpacity组件,确保不透明
  314. const opacityComp = this.summaryPanel.getComponent(UIOpacity);
  315. if (opacityComp) {
  316. console.log('设置summaryPanel的不透明度为255');
  317. opacityComp.opacity = 255;
  318. }
  319. // 如果有widget组件,可能需要更新对齐
  320. const widgetComp = this.summaryPanel.getComponent(Widget);
  321. if (widgetComp) {
  322. console.log('更新summaryPanel的Widget对齐');
  323. widgetComp.updateAlignment();
  324. }
  325. // 检查summaryPanel的位置和大小
  326. console.log('summaryPanel位置:', this.summaryPanel.position);
  327. const uiTransform = this.summaryPanel.getComponent(UITransform);
  328. if (uiTransform) {
  329. console.log('summaryPanel大小:', uiTransform.contentSize);
  330. } else {
  331. console.log('summaryPanel没有UITransform组件');
  332. }
  333. console.log('summaryPanel缩放:', this.summaryPanel.scale);
  334. console.log('summaryPanel角度:', this.summaryPanel.angle);
  335. console.log('summaryPanel激活状态:', this.summaryPanel.active);
  336. // 检查summaryPanel的子节点状态
  337. const children = this.summaryPanel.children;
  338. console.log(`summaryPanel有 ${children.length} 个子节点`);
  339. children.forEach((child, index) => {
  340. console.log(`子节点 ${index}: ${child.name}, 激活状态: ${child.active}`);
  341. });
  342. // 更新UI显示
  343. this.updateSummaryUI();
  344. console.log('成功激活summaryPanel,位置:', this.summaryPanel.position);
  345. // 添加延迟操作,确保UI正确显示
  346. this.scheduleOnce(() => {
  347. console.log('延迟处理:再次确认summaryPanel是否显示');
  348. if (this.summaryPanel) {
  349. if (!this.summaryPanel.active) {
  350. console.log('延迟处理:summaryPanel未激活,尝试再次激活');
  351. this.summaryPanel.active = true;
  352. }
  353. // 再次确保位于最顶层
  354. this.summaryPanel.setSiblingIndex(999);
  355. // 再次强制更新UI显示
  356. this.updateSummaryUI();
  357. console.log('延迟处理:summaryPanel状态:', this.summaryPanel.active);
  358. }
  359. }, 0.1); // 延迟0.1秒
  360. }
  361. /**
  362. * 强制将总结面板移动到场景最顶层
  363. */
  364. private forceMoveToTop(): void {
  365. console.log('尝试强制将总结面板移动到最顶层');
  366. // 查找当前场景的Canvas
  367. const scene = director.getScene();
  368. if (!scene) {
  369. console.error('无法获取当前场景');
  370. return;
  371. }
  372. console.log('当前场景:', scene.name);
  373. // 遍历场景节点查找Canvas
  374. let canvasNode = null;
  375. const findCanvas = (node: Node) => {
  376. if (node.getComponent(Canvas)) {
  377. canvasNode = node;
  378. return true;
  379. }
  380. for (let i = 0; i < node.children.length; i++) {
  381. if (findCanvas(node.children[i])) {
  382. return true;
  383. }
  384. }
  385. return false;
  386. };
  387. findCanvas(scene);
  388. if (canvasNode) {
  389. console.log('找到Canvas节点:', canvasNode.name);
  390. // 如果summaryPanel不在Canvas下,尝试将其移动到Canvas
  391. if (this.summaryPanel.parent !== canvasNode) {
  392. console.log('summaryPanel不在Canvas下,尝试移动');
  393. // 保存原始父节点以便恢复
  394. const originalParent = this.summaryPanel.parent;
  395. // 记录当前位置
  396. const originalPosition = this.summaryPanel.position.clone();
  397. // 尝试将面板添加到Canvas
  398. this.summaryPanel.parent = canvasNode;
  399. this.summaryPanel.setSiblingIndex(canvasNode.children.length - 1);
  400. console.log('summaryPanel已移动到Canvas下,索引:', this.summaryPanel.getSiblingIndex());
  401. } else {
  402. console.log('summaryPanel已在Canvas下,设置最高索引');
  403. this.summaryPanel.setSiblingIndex(canvasNode.children.length - 1);
  404. }
  405. } else {
  406. console.error('场景中未找到Canvas节点');
  407. }
  408. }
  409. /**
  410. * 隐藏总结面板
  411. */
  412. public hideSummaryPanel(): void {
  413. console.log('SummaryManager.hideSummaryPanel被调用');
  414. // 更新显示标志
  415. this.isShowingSummary = false;
  416. if (this.summaryPanel) {
  417. this.summaryPanel.active = false;
  418. console.log('总结面板已隐藏');
  419. } else {
  420. console.error('summaryPanel未设置,无法隐藏');
  421. }
  422. }
  423. /**
  424. * 更新总结UI显示
  425. */
  426. private updateSummaryUI(): void {
  427. console.log('updateSummaryUI被调用,准备更新UI显示');
  428. // 检查标签引用是否存在
  429. if (!this.passedRealCountLabel) {
  430. console.error('passedRealCountLabel未设置');
  431. } else {
  432. console.log(`设置放行邻居数量: ${this.gameStats.passedRealCount}`);
  433. this.passedRealCountLabel.string = String(this.gameStats.passedRealCount);
  434. }
  435. if (!this.dismissedFakeCountLabel) {
  436. console.error('dismissedFakeCountLabel未设置');
  437. } else {
  438. console.log(`设置驱赶伪人数量: ${this.gameStats.dismissedFakeCount}`);
  439. this.dismissedFakeCountLabel.string = String(this.gameStats.dismissedFakeCount);
  440. }
  441. if (!this.passedFakeCountLabel) {
  442. console.error('passedFakeCountLabel未设置');
  443. } else {
  444. console.log(`设置放行伪人数量: ${this.gameStats.passedFakeCount}`);
  445. this.passedFakeCountLabel.string = String(this.gameStats.passedFakeCount);
  446. }
  447. if (!this.dismissedRealCountLabel) {
  448. console.error('dismissedRealCountLabel未设置');
  449. } else {
  450. console.log(`设置驱赶邻居数量: ${this.gameStats.dismissedRealCount}`);
  451. this.dismissedRealCountLabel.string = String(this.gameStats.dismissedRealCount);
  452. }
  453. // 更新等级评分
  454. if (!this.gradeLabel) {
  455. console.error('gradeLabel未设置');
  456. } else {
  457. console.log(`设置评分等级: ${this.gameStats.grade}`);
  458. this.gradeLabel.string = this.gameStats.grade;
  459. }
  460. // 检查按钮状态
  461. console.log(`放行伪人列表数量: ${this.gameStats.passedFakeList.length}`);
  462. if (this.viewPassedFakeButton) {
  463. // 根据列表是否有内容来启用/禁用按钮
  464. this.viewPassedFakeButton.interactable = this.gameStats.passedFakeList.length > 0;
  465. console.log(`设置放行伪人详情按钮状态: ${this.viewPassedFakeButton.interactable}`);
  466. } else {
  467. console.error('viewPassedFakeButton未设置');
  468. }
  469. console.log(`驱赶邻居列表数量: ${this.gameStats.dismissedRealList.length}`);
  470. if (this.viewDismissedRealButton) {
  471. // 根据列表是否有内容来启用/禁用按钮
  472. this.viewDismissedRealButton.interactable = this.gameStats.dismissedRealList.length > 0;
  473. console.log(`设置驱赶邻居详情按钮状态: ${this.viewDismissedRealButton.interactable}`);
  474. } else {
  475. console.error('viewDismissedRealButton未设置');
  476. }
  477. console.log('UI显示更新完成');
  478. }
  479. /**
  480. * 显示详情面板
  481. * @param detailType 详情类型
  482. */
  483. private showDetailPanel(detailType: 'passedFake' | 'dismissedReal'): void {
  484. if (!this.detailPanel || !this.detailContentContainer) return;
  485. this.currentDetailType = detailType;
  486. // 设置标题
  487. if (this.detailTitleLabel) {
  488. this.detailTitleLabel.string = detailType === 'passedFake' ? '放进来的伪人' : '驱赶的邻居';
  489. }
  490. // 清空容器
  491. this.detailContentContainer.removeAllChildren();
  492. // 获取详情列表
  493. const detailList = detailType === 'passedFake' ?
  494. this.gameStats.passedFakeList : this.gameStats.dismissedRealList;
  495. // 创建详情条目
  496. detailList.forEach(detail => {
  497. this.createDetailItem(detail);
  498. });
  499. // 显示面板
  500. this.detailPanel.active = true;
  501. this.detailPanel.setSiblingIndex(1000); // 确保显示在总结面板之上
  502. }
  503. /**
  504. * 隐藏详情面板
  505. */
  506. private hideDetailPanel(): void {
  507. if (this.detailPanel) {
  508. this.detailPanel.active = false;
  509. }
  510. }
  511. /**
  512. * 创建详情条目
  513. * @param detailData 详情数据
  514. */
  515. private createDetailItem(detailData: DetailItemData): void {
  516. if (!this.detailItemPrefab || !this.detailContentContainer) return;
  517. console.log(`创建详情条目: ${detailData.name}, 头像路径: ${detailData.avatarPath}, 类型: ${this.currentDetailType}`);
  518. // 实例化预制体
  519. const itemNode = instantiate(this.detailItemPrefab);
  520. this.detailContentContainer.addChild(itemNode);
  521. // 设置名称
  522. const nameLabel = itemNode.getChildByName('Name')?.getComponent(Label);
  523. if (nameLabel) {
  524. nameLabel.string = detailData.name;
  525. }
  526. // 设置头像
  527. const avatarSprite = itemNode.getChildByName('Avatar')?.getComponent(Sprite);
  528. if (avatarSprite) {
  529. // 列出所有可能尝试的路径格式
  530. let pathsToTry = [];
  531. if (this.currentDetailType === 'passedFake') {
  532. // 如果是"放行的伪人",使用黑影图片
  533. console.log('加载黑影头像');
  534. pathsToTry = [
  535. 'avatars/black/spriteFrame',
  536. 'avatars/black',
  537. 'avatars/黑影/spriteFrame',
  538. 'avatars/黑影',
  539. 'black/spriteFrame',
  540. 'black',
  541. '黑影/spriteFrame',
  542. '黑影'
  543. ];
  544. } else {
  545. // 如果是"驱赶的邻居"或其他,正常加载头像
  546. console.log(`加载角色头像: ${detailData.avatarPath}`);
  547. const baseAvatarPath = detailData.avatarPath;
  548. pathsToTry = [
  549. `${baseAvatarPath}/spriteFrame`,
  550. baseAvatarPath,
  551. `avatars/${detailData.characterId}/avatar_${detailData.characterId}_5/spriteFrame`,
  552. `avatars/${detailData.characterId}/avatar_${detailData.characterId}_5`,
  553. `avatars/${detailData.characterId}/spriteFrame`,
  554. `avatars/${detailData.characterId}`
  555. ];
  556. }
  557. // 递归尝试加载所有可能的路径
  558. this.tryLoadSpriteFrameWithPaths(avatarSprite, pathsToTry, 0);
  559. }
  560. // 设置查看详情按钮事件
  561. const detailButton = itemNode.getChildByName('DetailButton')?.getComponent(Button);
  562. if (detailButton) {
  563. detailButton.node.on(Button.EventType.CLICK, () => {
  564. this.showCharacterDetail(detailData.characterId);
  565. }, this);
  566. }
  567. }
  568. /**
  569. * 递归尝试加载所有可能的路径
  570. * @param sprite 要设置的精灵组件
  571. * @param paths 尝试的路径数组
  572. * @param index 当前尝试的路径索引
  573. */
  574. private tryLoadSpriteFrameWithPaths(sprite: Sprite, paths: string[], index: number): void {
  575. if (index >= paths.length) {
  576. console.error('所有可能的路径都尝试失败,使用默认图像');
  577. // 所有路径都失败,创建一个默认的灰色方形作为备用
  578. this.createDefaultSpriteFrame(sprite);
  579. return;
  580. }
  581. const currentPath = paths[index];
  582. console.log(`尝试加载路径(${index+1}/${paths.length}): ${currentPath}`);
  583. resources.load(currentPath, SpriteFrame, (err, spriteFrame) => {
  584. if (err) {
  585. console.warn(`路径加载失败: ${currentPath}`, err);
  586. // 尝试下一个路径
  587. this.tryLoadSpriteFrameWithPaths(sprite, paths, index + 1);
  588. return;
  589. }
  590. // 成功加载,设置spriteFrame
  591. sprite.spriteFrame = spriteFrame;
  592. console.log(`成功加载头像: ${currentPath}`);
  593. });
  594. }
  595. /**
  596. * 创建一个默认的SpriteFrame用于显示
  597. * @param sprite 要设置的精灵组件
  598. */
  599. private createDefaultSpriteFrame(sprite: Sprite): void {
  600. console.log('创建默认图像');
  601. // 使用内置资源或默认资源
  602. const defaultIcon = "default_sprite";
  603. resources.load(defaultIcon, SpriteFrame, (err, spriteFrame) => {
  604. if (err) {
  605. console.warn(`无法加载默认图像 ${defaultIcon}`, err);
  606. return;
  607. }
  608. sprite.spriteFrame = spriteFrame;
  609. console.log('已设置默认图像');
  610. });
  611. }
  612. /**
  613. * 显示角色详情
  614. * @param characterId 角色ID
  615. */
  616. private showCharacterDetail(characterId: number): void {
  617. if (!this.characterDetailPanel) return;
  618. console.log(`显示角色详情: ID=${characterId}`);
  619. // 获取角色数据
  620. const npcData = this.dataManager.getNPCById(characterId);
  621. if (!npcData) {
  622. console.error(`无法找到ID为${characterId}的NPC数据`);
  623. return;
  624. }
  625. console.log(`找到NPC数据: ${npcData.characterName}`);
  626. // 通过事件系统通知GameFlow处理
  627. // 或者提供一个回调函数由GameFlow注入
  628. if (this.onShowCharacterDetail) {
  629. console.log(`调用onShowCharacterDetail回调函数显示角色详情`);
  630. this.onShowCharacterDetail(characterId);
  631. } else {
  632. console.error(`onShowCharacterDetail回调未设置,无法显示角色详情`);
  633. }
  634. }
  635. /**
  636. * 重置统计数据
  637. */
  638. public resetStats(): void {
  639. console.log('SummaryManager.resetStats被调用,重置统计数据');
  640. this.gameStats = {
  641. passedRealCount: 0,
  642. dismissedFakeCount: 0,
  643. passedFakeCount: 0,
  644. dismissedRealCount: 0,
  645. passedRealList: [],
  646. dismissedFakeList: [],
  647. passedFakeList: [],
  648. dismissedRealList: [],
  649. grade: 'D'
  650. };
  651. // 重置显示标志,但不要隐藏面板
  652. this.isShowingSummary = false;
  653. console.log('统计数据已重置');
  654. }
  655. /**
  656. * 处理确认按钮点击
  657. */
  658. private handleConfirmButtonClick(): void {
  659. console.log('确认按钮被点击,准备切换到下一关');
  660. // 隐藏当前面板
  661. this.hideSummaryPanel();
  662. // 检查游戏流程管理器是否存在
  663. if (!this.gameFlowManager) {
  664. console.error('游戏流程管理器未设置,无法切换到下一关');
  665. return;
  666. }
  667. // 使用DataManager切换到下一关
  668. if (this.dataManager) {
  669. // 先重置统计数据
  670. this.resetStats();
  671. // 切换到下一关
  672. const hasNextLevel = this.dataManager.nextLevel();
  673. if (hasNextLevel) {
  674. console.log('成功切换到下一关,准备开始新关卡');
  675. // 重新开始游戏流程
  676. this.gameFlowManager.restartGameFlow();
  677. } else {
  678. console.log('已经是最后一关,游戏结束');
  679. // 这里可以添加游戏结束的处理逻辑
  680. // 例如显示通关画面等
  681. }
  682. } else {
  683. console.error('DataManager未设置,无法切换关卡');
  684. }
  685. }
  686. onEnable() {
  687. console.log('SummaryManager.onEnable被调用');
  688. // 如果正在显示总结面板,确保面板保持显示状态
  689. if (this.isShowingSummary && this.summaryPanel) {
  690. console.log('onEnable: 总结面板正在显示中,确保保持显示状态');
  691. this.summaryPanel.active = true;
  692. }
  693. }
  694. onDestroy() {
  695. // 清理按钮事件
  696. if (this.viewPassedFakeButton) {
  697. this.viewPassedFakeButton.node.off(Button.EventType.CLICK);
  698. }
  699. if (this.viewDismissedRealButton) {
  700. this.viewDismissedRealButton.node.off(Button.EventType.CLICK);
  701. }
  702. if (this.detailCloseButton) {
  703. this.detailCloseButton.node.off(Button.EventType.CLICK);
  704. }
  705. if (this.confirmButton) {
  706. this.confirmButton.node.off(Button.EventType.CLICK, this.handleConfirmButtonClick, this);
  707. }
  708. }
  709. /**
  710. * 检查头像资源目录结构
  711. */
  712. private checkAvatarResources(): void {
  713. console.log('检查avatars资源目录结构...');
  714. // 检查black图片是否存在
  715. resources.load('avatars/black/spriteFrame', SpriteFrame, (err, asset) => {
  716. if (err) {
  717. console.error('avatars/black不存在', err);
  718. } else {
  719. console.log('成功加载avatars/black');
  720. }
  721. });
  722. // 尝试列出avatars目录下的内容
  723. resources.loadDir('avatars', (err, assets) => {
  724. if (err) {
  725. console.error('无法加载avatars目录', err);
  726. return;
  727. }
  728. console.log(`avatars目录中有 ${assets.length} 个资源:`);
  729. assets.forEach((asset, index) => {
  730. console.log(`${index + 1}. ${asset.name} (类型: ${typeof asset})`);
  731. });
  732. });
  733. }
  734. }