import { _decorator, Component, Node, Label, Button, Sprite, SpriteFrame, resources, instantiate, UIOpacity, Widget, UITransform, director, Canvas, AssetManager } from 'cc'; import { DataManager } from './DataManager'; import { GameFlowManager } from './GameFlowManager'; const { ccclass, property } = _decorator; // 定义UI详情数据接口 interface DetailItemData { name: string; avatarPath: string; characterId: number; } // 定义统计结果类型 interface GameStats { passedRealCount: number; // 放行的邻居数量 dismissedFakeCount: number; // 驱赶的伪人数量 passedFakeCount: number; // 放行的伪人数量 dismissedRealCount: number; // 驱赶的邻居数量 passedRealList: DetailItemData[]; // 放行的邻居列表 dismissedFakeList: DetailItemData[]; // 驱赶的伪人列表 passedFakeList: DetailItemData[]; // 放行的伪人列表 dismissedRealList: DetailItemData[]; // 驱赶的邻居列表 grade: string; // 评分:A/B/C/D } @ccclass('SummaryManager') export class SummaryManager extends Component { @property({ type: Node, tooltip: '总结面板节点' }) summaryPanel: Node = null; @property({ type: Label, tooltip: '放行邻居数量文本' }) passedRealCountLabel: Label = null; @property({ type: Label, tooltip: '驱赶伪人数量文本' }) dismissedFakeCountLabel: Label = null; @property({ type: Label, tooltip: '放行伪人数量文本' }) passedFakeCountLabel: Label = null; @property({ type: Label, tooltip: '驱赶邻居数量文本' }) dismissedRealCountLabel: Label = null; @property({ type: Label, tooltip: '等级评分文本' }) gradeLabel: Label = null; @property({ type: Button, tooltip: '查看放行伪人详情按钮' }) viewPassedFakeButton: Button = null; @property({ type: Button, tooltip: '查看驱赶邻居详情按钮' }) viewDismissedRealButton: Button = null; @property({ type: Node, tooltip: '详情面板节点' }) detailPanel: Node = null; @property({ type: Label, tooltip: '详情面板标题' }) detailTitleLabel: Label = null; @property({ type: Node, tooltip: '详情内容容器节点' }) detailContentContainer: Node = null; @property({ type: Node, tooltip: '详情条目预制体' }) detailItemPrefab: Node = null; @property({ type: Button, tooltip: '详情面板关闭按钮' }) detailCloseButton: Button = null; @property({ type: Node, tooltip: '角色详情面板' }) characterDetailPanel: Node = null; @property({ type: DataManager, tooltip: '数据管理器引用' }) dataManager: DataManager = null; @property({ type: Button, tooltip: '确认按钮' }) confirmButton: Button = null; @property({ type: GameFlowManager, tooltip: '游戏流程管理器引用' }) gameFlowManager: GameFlowManager = null; // 游戏统计数据 private gameStats: GameStats = { passedRealCount: 0, dismissedFakeCount: 0, passedFakeCount: 0, dismissedRealCount: 0, passedRealList: [], dismissedFakeList: [], passedFakeList: [], dismissedRealList: [], grade: 'D' }; // 当前显示的详情类型 private currentDetailType: 'passedFake' | 'dismissedReal' = null; // 在SummaryManager中添加回调属性 public onShowCharacterDetail: (characterId: number) => void = null; // 添加初始化标记 private isInitialized: boolean = false; // 添加标记表示是否正在显示总结面板 private isShowingSummary: boolean = false; start() { console.log('SummaryManager.start被调用'); // 避免重复初始化 if (this.isInitialized) { console.log('SummaryManager已经初始化过,跳过初始化流程'); return; } // 如果正在显示总结面板,跳过隐藏面板的步骤 if (this.isShowingSummary) { console.log('总结面板正在显示中,跳过隐藏面板的初始化步骤'); this.isInitialized = true; this.setupButtons(); return; } // 检查面板引用 if (!this.summaryPanel) { console.error('summaryPanel未被赋值,请检查Inspector中的引用设置'); } else { console.log('summaryPanel初始状态:', this.summaryPanel.active); // 初始化隐藏面板,但先记录下它的初始状态以便调试 this.summaryPanel.active = false; console.log('summaryPanel已设置为隐藏'); } if (!this.detailPanel) { console.error('detailPanel未被赋值,请检查Inspector中的引用设置'); } else { console.log('detailPanel初始状态:', this.detailPanel.active); this.detailPanel.active = false; console.log('detailPanel已设置为隐藏'); } if (!this.characterDetailPanel) { console.error('characterDetailPanel未被赋值,请检查Inspector中的引用设置'); } else { console.log('characterDetailPanel初始状态:', this.characterDetailPanel.active); this.characterDetailPanel.active = false; console.log('characterDetailPanel已设置为隐藏'); } // 注册按钮事件 this.setupButtons(); // 标记为已初始化 this.isInitialized = true; } /** * 设置按钮事件 */ private setupButtons(): void { // 查看放行伪人详情按钮 if (this.viewPassedFakeButton) { this.viewPassedFakeButton.node.on(Button.EventType.CLICK, () => { this.showDetailPanel('passedFake'); }, this); } // 查看驱赶邻居详情按钮 if (this.viewDismissedRealButton) { this.viewDismissedRealButton.node.on(Button.EventType.CLICK, () => { this.showDetailPanel('dismissedReal'); }, this); } // 详情面板关闭按钮 if (this.detailCloseButton) { this.detailCloseButton.node.on(Button.EventType.CLICK, () => { this.hideDetailPanel(); }, this); } // 确认按钮 if (this.confirmButton) { this.confirmButton.node.on(Button.EventType.CLICK, this.handleConfirmButtonClick, this); } else { console.error('确认按钮未设置'); } } /** * 记录放行NPC * @param npcData NPC数据 */ public recordPassedNPC(npcData: any): void { if (!npcData) return; console.log(`记录放行NPC: ${npcData.characterName}, 类型: ${npcData.type}, ID: ${npcData.characterId}`); const detailData: DetailItemData = { name: npcData.characterName, avatarPath: `avatars/${npcData.characterId}/avatar_${npcData.characterId}_5`, characterId: npcData.characterId }; if (npcData.type === 'real') { // 放行了邻居 this.gameStats.passedRealCount++; this.gameStats.passedRealList.push(detailData); console.log(`放行邻居数量增加到 ${this.gameStats.passedRealCount}`); } else if (npcData.type === 'fake') { // 放行了伪人 this.gameStats.passedFakeCount++; this.gameStats.passedFakeList.push(detailData); console.log(`放行伪人数量增加到 ${this.gameStats.passedFakeCount}`); } // 更新评分 this.updateGrade(); } /** * 记录驱赶NPC * @param npcData NPC数据 */ public recordDismissedNPC(npcData: any): void { if (!npcData) return; console.log(`记录驱赶NPC: ${npcData.characterName}, 类型: ${npcData.type}, ID: ${npcData.characterId}`); const detailData: DetailItemData = { name: npcData.characterName, avatarPath: `avatars/${npcData.characterId}/avatar_${npcData.characterId}_5`, characterId: npcData.characterId }; if (npcData.type === 'real') { // 驱赶了邻居 this.gameStats.dismissedRealCount++; this.gameStats.dismissedRealList.push(detailData); console.log(`驱赶邻居数量增加到 ${this.gameStats.dismissedRealCount}`); } else if (npcData.type === 'fake') { // 驱赶了伪人 this.gameStats.dismissedFakeCount++; this.gameStats.dismissedFakeList.push(detailData); console.log(`驱赶伪人数量增加到 ${this.gameStats.dismissedFakeCount}`); } // 更新评分 this.updateGrade(); } /** * 更新评分 */ private updateGrade(): void { // 计算正确决策的百分比 const totalDecisions = this.gameStats.passedRealCount + this.gameStats.dismissedFakeCount + this.gameStats.passedFakeCount + this.gameStats.dismissedRealCount; if (totalDecisions === 0) { this.gameStats.grade = 'D'; return; } const correctDecisions = this.gameStats.passedRealCount + this.gameStats.dismissedFakeCount; const correctPercentage = (correctDecisions / totalDecisions) * 100; // 根据正确率确定等级 if (correctPercentage >= 90) { this.gameStats.grade = 'A'; } else if (correctPercentage >= 70) { this.gameStats.grade = 'B'; } else if (correctPercentage >= 50) { this.gameStats.grade = 'C'; } else { this.gameStats.grade = 'D'; } } /** * 显示总结面板 */ public showSummaryPanel(): void { console.log('SummaryManager.showSummaryPanel被调用'); // 尝试检查资源路径 this.checkAvatarResources(); // 标记为正在显示总结面板 this.isShowingSummary = true; // 确保已初始化 if (!this.isInitialized) { console.log('SummaryManager未初始化,执行初始化'); this.isInitialized = true; // 标记为已初始化,避免start中再次隐藏面板 } if (!this.summaryPanel) { console.error('summaryPanel未设置'); return; } // 检查summaryPanel的父节点状态 const parentNode = this.summaryPanel.parent; if (parentNode) { console.log('summaryPanel父节点状态:', parentNode.name, '激活状态:', parentNode.active); // 确保父节点也是激活的 if (!parentNode.active) { console.log('激活summaryPanel的父节点'); parentNode.active = true; } } else { console.error('summaryPanel没有父节点'); } // 强制设置可见性相关属性 this.summaryPanel.active = true; // 确保位于最顶层 this.summaryPanel.setSiblingIndex(999); // 尝试强制将面板移动到场景顶层 this.forceMoveToTop(); // 如果节点有UIOpacity组件,确保不透明 const opacityComp = this.summaryPanel.getComponent(UIOpacity); if (opacityComp) { console.log('设置summaryPanel的不透明度为255'); opacityComp.opacity = 255; } // 如果有widget组件,可能需要更新对齐 const widgetComp = this.summaryPanel.getComponent(Widget); if (widgetComp) { console.log('更新summaryPanel的Widget对齐'); widgetComp.updateAlignment(); } // 检查summaryPanel的位置和大小 console.log('summaryPanel位置:', this.summaryPanel.position); const uiTransform = this.summaryPanel.getComponent(UITransform); if (uiTransform) { console.log('summaryPanel大小:', uiTransform.contentSize); } else { console.log('summaryPanel没有UITransform组件'); } console.log('summaryPanel缩放:', this.summaryPanel.scale); console.log('summaryPanel角度:', this.summaryPanel.angle); console.log('summaryPanel激活状态:', this.summaryPanel.active); // 检查summaryPanel的子节点状态 const children = this.summaryPanel.children; console.log(`summaryPanel有 ${children.length} 个子节点`); children.forEach((child, index) => { console.log(`子节点 ${index}: ${child.name}, 激活状态: ${child.active}`); }); // 更新UI显示 this.updateSummaryUI(); console.log('成功激活summaryPanel,位置:', this.summaryPanel.position); // 添加延迟操作,确保UI正确显示 this.scheduleOnce(() => { console.log('延迟处理:再次确认summaryPanel是否显示'); if (this.summaryPanel) { if (!this.summaryPanel.active) { console.log('延迟处理:summaryPanel未激活,尝试再次激活'); this.summaryPanel.active = true; } // 再次确保位于最顶层 this.summaryPanel.setSiblingIndex(999); // 再次强制更新UI显示 this.updateSummaryUI(); console.log('延迟处理:summaryPanel状态:', this.summaryPanel.active); } }, 0.1); // 延迟0.1秒 } /** * 强制将总结面板移动到场景最顶层 */ private forceMoveToTop(): void { console.log('尝试强制将总结面板移动到最顶层'); // 查找当前场景的Canvas const scene = director.getScene(); if (!scene) { console.error('无法获取当前场景'); return; } console.log('当前场景:', scene.name); // 遍历场景节点查找Canvas let canvasNode = null; const findCanvas = (node: Node) => { if (node.getComponent(Canvas)) { canvasNode = node; return true; } for (let i = 0; i < node.children.length; i++) { if (findCanvas(node.children[i])) { return true; } } return false; }; findCanvas(scene); if (canvasNode) { console.log('找到Canvas节点:', canvasNode.name); // 如果summaryPanel不在Canvas下,尝试将其移动到Canvas if (this.summaryPanel.parent !== canvasNode) { console.log('summaryPanel不在Canvas下,尝试移动'); // 保存原始父节点以便恢复 const originalParent = this.summaryPanel.parent; // 记录当前位置 const originalPosition = this.summaryPanel.position.clone(); // 尝试将面板添加到Canvas this.summaryPanel.parent = canvasNode; this.summaryPanel.setSiblingIndex(canvasNode.children.length - 1); console.log('summaryPanel已移动到Canvas下,索引:', this.summaryPanel.getSiblingIndex()); } else { console.log('summaryPanel已在Canvas下,设置最高索引'); this.summaryPanel.setSiblingIndex(canvasNode.children.length - 1); } } else { console.error('场景中未找到Canvas节点'); } } /** * 隐藏总结面板 */ public hideSummaryPanel(): void { console.log('SummaryManager.hideSummaryPanel被调用'); // 更新显示标志 this.isShowingSummary = false; if (this.summaryPanel) { this.summaryPanel.active = false; console.log('总结面板已隐藏'); } else { console.error('summaryPanel未设置,无法隐藏'); } } /** * 更新总结UI显示 */ private updateSummaryUI(): void { console.log('updateSummaryUI被调用,准备更新UI显示'); // 检查标签引用是否存在 if (!this.passedRealCountLabel) { console.error('passedRealCountLabel未设置'); } else { console.log(`设置放行邻居数量: ${this.gameStats.passedRealCount}`); this.passedRealCountLabel.string = String(this.gameStats.passedRealCount); } if (!this.dismissedFakeCountLabel) { console.error('dismissedFakeCountLabel未设置'); } else { console.log(`设置驱赶伪人数量: ${this.gameStats.dismissedFakeCount}`); this.dismissedFakeCountLabel.string = String(this.gameStats.dismissedFakeCount); } if (!this.passedFakeCountLabel) { console.error('passedFakeCountLabel未设置'); } else { console.log(`设置放行伪人数量: ${this.gameStats.passedFakeCount}`); this.passedFakeCountLabel.string = String(this.gameStats.passedFakeCount); } if (!this.dismissedRealCountLabel) { console.error('dismissedRealCountLabel未设置'); } else { console.log(`设置驱赶邻居数量: ${this.gameStats.dismissedRealCount}`); this.dismissedRealCountLabel.string = String(this.gameStats.dismissedRealCount); } // 更新等级评分 if (!this.gradeLabel) { console.error('gradeLabel未设置'); } else { console.log(`设置评分等级: ${this.gameStats.grade}`); this.gradeLabel.string = this.gameStats.grade; } // 检查按钮状态 console.log(`放行伪人列表数量: ${this.gameStats.passedFakeList.length}`); if (this.viewPassedFakeButton) { // 根据列表是否有内容来启用/禁用按钮 this.viewPassedFakeButton.interactable = this.gameStats.passedFakeList.length > 0; console.log(`设置放行伪人详情按钮状态: ${this.viewPassedFakeButton.interactable}`); } else { console.error('viewPassedFakeButton未设置'); } console.log(`驱赶邻居列表数量: ${this.gameStats.dismissedRealList.length}`); if (this.viewDismissedRealButton) { // 根据列表是否有内容来启用/禁用按钮 this.viewDismissedRealButton.interactable = this.gameStats.dismissedRealList.length > 0; console.log(`设置驱赶邻居详情按钮状态: ${this.viewDismissedRealButton.interactable}`); } else { console.error('viewDismissedRealButton未设置'); } console.log('UI显示更新完成'); } /** * 显示详情面板 * @param detailType 详情类型 */ private showDetailPanel(detailType: 'passedFake' | 'dismissedReal'): void { if (!this.detailPanel || !this.detailContentContainer) return; this.currentDetailType = detailType; // 设置标题 if (this.detailTitleLabel) { this.detailTitleLabel.string = detailType === 'passedFake' ? '放进来的伪人' : '驱赶的邻居'; } // 清空容器 this.detailContentContainer.removeAllChildren(); // 获取详情列表 const detailList = detailType === 'passedFake' ? this.gameStats.passedFakeList : this.gameStats.dismissedRealList; // 创建详情条目 detailList.forEach(detail => { this.createDetailItem(detail); }); // 显示面板 this.detailPanel.active = true; this.detailPanel.setSiblingIndex(1000); // 确保显示在总结面板之上 } /** * 隐藏详情面板 */ private hideDetailPanel(): void { if (this.detailPanel) { this.detailPanel.active = false; } } /** * 创建详情条目 * @param detailData 详情数据 */ private createDetailItem(detailData: DetailItemData): void { if (!this.detailItemPrefab || !this.detailContentContainer) return; console.log(`创建详情条目: ${detailData.name}, 头像路径: ${detailData.avatarPath}, 类型: ${this.currentDetailType}`); // 实例化预制体 const itemNode = instantiate(this.detailItemPrefab); this.detailContentContainer.addChild(itemNode); // 设置名称 const nameLabel = itemNode.getChildByName('Name')?.getComponent(Label); if (nameLabel) { nameLabel.string = detailData.name; } // 设置头像 const avatarSprite = itemNode.getChildByName('Avatar')?.getComponent(Sprite); if (avatarSprite) { // 列出所有可能尝试的路径格式 let pathsToTry = []; if (this.currentDetailType === 'passedFake') { // 如果是"放行的伪人",使用黑影图片 console.log('加载黑影头像'); pathsToTry = [ 'avatars/black/spriteFrame', 'avatars/black', 'avatars/黑影/spriteFrame', 'avatars/黑影', 'black/spriteFrame', 'black', '黑影/spriteFrame', '黑影' ]; } else { // 如果是"驱赶的邻居"或其他,正常加载头像 console.log(`加载角色头像: ${detailData.avatarPath}`); const baseAvatarPath = detailData.avatarPath; pathsToTry = [ `${baseAvatarPath}/spriteFrame`, baseAvatarPath, `avatars/${detailData.characterId}/avatar_${detailData.characterId}_5/spriteFrame`, `avatars/${detailData.characterId}/avatar_${detailData.characterId}_5`, `avatars/${detailData.characterId}/spriteFrame`, `avatars/${detailData.characterId}` ]; } // 递归尝试加载所有可能的路径 this.tryLoadSpriteFrameWithPaths(avatarSprite, pathsToTry, 0); } // 设置查看详情按钮事件 const detailButton = itemNode.getChildByName('DetailButton')?.getComponent(Button); if (detailButton) { detailButton.node.on(Button.EventType.CLICK, () => { this.showCharacterDetail(detailData.characterId); }, this); } } /** * 递归尝试加载所有可能的路径 * @param sprite 要设置的精灵组件 * @param paths 尝试的路径数组 * @param index 当前尝试的路径索引 */ private tryLoadSpriteFrameWithPaths(sprite: Sprite, paths: string[], index: number): void { if (index >= paths.length) { console.error('所有可能的路径都尝试失败,使用默认图像'); // 所有路径都失败,创建一个默认的灰色方形作为备用 this.createDefaultSpriteFrame(sprite); return; } const currentPath = paths[index]; console.log(`尝试加载路径(${index+1}/${paths.length}): ${currentPath}`); resources.load(currentPath, SpriteFrame, (err, spriteFrame) => { if (err) { console.warn(`路径加载失败: ${currentPath}`, err); // 尝试下一个路径 this.tryLoadSpriteFrameWithPaths(sprite, paths, index + 1); return; } // 成功加载,设置spriteFrame sprite.spriteFrame = spriteFrame; console.log(`成功加载头像: ${currentPath}`); }); } /** * 创建一个默认的SpriteFrame用于显示 * @param sprite 要设置的精灵组件 */ private createDefaultSpriteFrame(sprite: Sprite): void { console.log('创建默认图像'); // 使用内置资源或默认资源 const defaultIcon = "default_sprite"; resources.load(defaultIcon, SpriteFrame, (err, spriteFrame) => { if (err) { console.warn(`无法加载默认图像 ${defaultIcon}`, err); return; } sprite.spriteFrame = spriteFrame; console.log('已设置默认图像'); }); } /** * 显示角色详情 * @param characterId 角色ID */ private showCharacterDetail(characterId: number): void { if (!this.characterDetailPanel) return; console.log(`显示角色详情: ID=${characterId}`); // 获取角色数据 const npcData = this.dataManager.getNPCById(characterId); if (!npcData) { console.error(`无法找到ID为${characterId}的NPC数据`); return; } console.log(`找到NPC数据: ${npcData.characterName}`); // 通过事件系统通知GameFlow处理 // 或者提供一个回调函数由GameFlow注入 if (this.onShowCharacterDetail) { console.log(`调用onShowCharacterDetail回调函数显示角色详情`); this.onShowCharacterDetail(characterId); } else { console.error(`onShowCharacterDetail回调未设置,无法显示角色详情`); } } /** * 重置统计数据 */ public resetStats(): void { console.log('SummaryManager.resetStats被调用,重置统计数据'); this.gameStats = { passedRealCount: 0, dismissedFakeCount: 0, passedFakeCount: 0, dismissedRealCount: 0, passedRealList: [], dismissedFakeList: [], passedFakeList: [], dismissedRealList: [], grade: 'D' }; // 重置显示标志,但不要隐藏面板 this.isShowingSummary = false; console.log('统计数据已重置'); } /** * 处理确认按钮点击 */ private handleConfirmButtonClick(): void { console.log('确认按钮被点击,准备切换到下一关'); // 隐藏当前面板 this.hideSummaryPanel(); // 检查游戏流程管理器是否存在 if (!this.gameFlowManager) { console.error('游戏流程管理器未设置,无法切换到下一关'); return; } // 使用DataManager切换到下一关 if (this.dataManager) { // 先重置统计数据 this.resetStats(); // 切换到下一关 const hasNextLevel = this.dataManager.nextLevel(); if (hasNextLevel) { console.log('成功切换到下一关,准备开始新关卡'); // 重新开始游戏流程 this.gameFlowManager.restartGameFlow(); } else { console.log('已经是最后一关,游戏结束'); // 这里可以添加游戏结束的处理逻辑 // 例如显示通关画面等 } } else { console.error('DataManager未设置,无法切换关卡'); } } onEnable() { console.log('SummaryManager.onEnable被调用'); // 如果正在显示总结面板,确保面板保持显示状态 if (this.isShowingSummary && this.summaryPanel) { console.log('onEnable: 总结面板正在显示中,确保保持显示状态'); this.summaryPanel.active = true; } } onDestroy() { // 清理按钮事件 if (this.viewPassedFakeButton) { this.viewPassedFakeButton.node.off(Button.EventType.CLICK); } if (this.viewDismissedRealButton) { this.viewDismissedRealButton.node.off(Button.EventType.CLICK); } if (this.detailCloseButton) { this.detailCloseButton.node.off(Button.EventType.CLICK); } if (this.confirmButton) { this.confirmButton.node.off(Button.EventType.CLICK, this.handleConfirmButtonClick, this); } } /** * 检查头像资源目录结构 */ private checkAvatarResources(): void { console.log('检查avatars资源目录结构...'); // 检查black图片是否存在 resources.load('avatars/black/spriteFrame', SpriteFrame, (err, asset) => { if (err) { console.error('avatars/black不存在', err); } else { console.log('成功加载avatars/black'); } }); // 尝试列出avatars目录下的内容 resources.loadDir('avatars', (err, assets) => { if (err) { console.error('无法加载avatars目录', err); return; } console.log(`avatars目录中有 ${assets.length} 个资源:`); assets.forEach((asset, index) => { console.log(`${index + 1}. ${asset.name} (类型: ${typeof asset})`); }); }); } }