export default class TmpScene extends Phaser.Scene { constructor() { super('TmpScene') // 定义类成员变量 this.infoBarVisible = false; // 信息栏是否可见 this.infoBar = null; // 信息栏对象 this.infoBarToggle = null; // 信息栏展开/收起按钮 this.infoBarContainer = null; // 信息栏容器 this.infoBarScrollContainer = null; // 滚动容器 this.infoBarComponents = {}; // 组件管理对象 this.infoBarConfig = { // 信息栏配置 width: 0, height: 0, components: {}, // 组件配置 autoCleanup: true, // 是否自动清理资源密集型组件 scrollable: true // 是否支持滚动 }; // 滚动相关变量 this.scrollY = 0; this.maxScrollY = 0; this.isDragging = false; this.lastDragY = 0; } create() { // 设置背景色 this.cameras.main.setBackgroundColor('#333333'); // 获取屏幕宽度和高度 this.screenWidth = this.scale.width; this.screenHeight = this.scale.height; // 创建右侧信息栏 this.createRightInfoBar(); // 示例:添加不同类型的组件,带固定高度和自定义顺序 this.addInfoBarComponent('playerStats', { type: 'text', title: '角色状态', content: ['生命值: 100/100', '魔法值: 50/50', '等级: 1'], enabled: true, resourceIntensive: false, height: 120, // 固定高度 order: 1 // 自定义顺序 }); this.addInfoBarComponent('miniMap', { type: 'placeholder', // 占位符,实际项目中替换为真实小地图 title: '小地图', content: ['小地图区域'], enabled: true, resourceIntensive: true, height: 180, // 固定高度 order: 2 // 自定义顺序 }); this.addInfoBarComponent('gameLog', { type: 'text', title: '游戏日志', content: ['系统: 欢迎来到游戏', '提示: 按H查看帮助', '新任务: 探索未知区域', '提示: 按I打开背包'], enabled: true, resourceIntensive: false, height: 160, // 固定高度 order: 3 // 自定义顺序 }); // 初始化时,如果信息栏可见,创建所有启用的组件 if (this.infoBarVisible) { this.createAllEnabledComponents(); } } // 创建所有启用的组件 createAllEnabledComponents() { // 按自定义顺序创建组件 const orderedComponents = this.getOrderedComponents(); orderedComponents.forEach(({id, config}) => { if (config.enabled) { this.createComponentInstance(id, config.config); } }); // 重新排列组件 this.rearrangeComponents(); // 更新滚动区域 this.updateScrollArea(); } // 获取按自定义顺序排序的组件 getOrderedComponents() { return Object.entries(this.infoBarConfig.components) .map(([id, config]) => ({id, config})) .sort((a, b) => { const orderA = a.config.config.order || 0; const orderB = b.config.config.order || 0; return orderA - orderB; }); } // 创建右侧信息栏 createRightInfoBar() { // 定义信息栏宽度 this.infoBarConfig.width = this.screenWidth * 0.2; // 创建信息栏容器 this.infoBarContainer = this.add.container( this.screenWidth, // 初始位置在屏幕右侧外 0 ); // 创建信息栏背景 const infoBarBg = this.add.rectangle( 0, // 相对于容器的位置 0, // 相对于容器的位置 this.infoBarConfig.width, this.screenHeight, 0x222222, // 背景色 0.9 // 透明度 ).setOrigin(1, 0); // 锚点在右上角 // 创建滚动容器,用于容纳所有组件 this.infoBarScrollContainer = this.add.container( -this.infoBarConfig.width, // 相对于信息栏容器的位置 0 ); // 将背景和滚动容器添加到信息栏容器 this.infoBarContainer.add([infoBarBg, this.infoBarScrollContainer]); // 添加滚动功能 if (this.infoBarConfig.scrollable) { this.setupScrolling(); } // 创建信息栏展开/收起按钮,固定在屏幕右上角 this.infoBarToggle = this.add.text( this.screenWidth - 40, // 按钮位置 20, '+', // 初始文本 { fontSize: '24px', fill: '#ffffff', backgroundColor: '#444444', padding: { x: 10, y: 5 } } ).setOrigin(0.5, 0.5).setInteractive(); // 添加点击事件 this.infoBarToggle.on('pointerdown', () => { this.toggleInfoBar(); }); // 保存信息栏对象,便于其他系统更新 this.infoBar = { container: this.infoBarContainer, scrollContainer: this.infoBarScrollContainer, toggle: this.infoBarToggle, bg: infoBarBg, config: this.infoBarConfig, components: this.infoBarComponents }; } // 设置滚动功能 setupScrolling() { // 移除遮罩,使用简单的滚动方式 // 添加鼠标事件监听 this.input.on('pointerdown', (pointer) => { // 检查点击是否在信息栏区域内 const infoBarRect = new Phaser.Geom.Rectangle( this.screenWidth - this.infoBarConfig.width, 0, this.infoBarConfig.width, this.screenHeight ); if (Phaser.Geom.Rectangle.ContainsPoint(infoBarRect, pointer) && this.infoBarVisible) { this.isDragging = true; this.lastDragY = pointer.y; } }); this.input.on('pointermove', (pointer) => { if (this.isDragging) { const deltaY = pointer.y - this.lastDragY; this.scroll(deltaY); this.lastDragY = pointer.y; } }); this.input.on('pointerup', () => { this.isDragging = false; }); // 添加触摸事件支持 this.input.on('touchstart', (pointer) => { this.input.emit('pointerdown', pointer); }); this.input.on('touchmove', (pointer) => { this.input.emit('pointermove', pointer); }); this.input.on('touchend', () => { this.input.emit('pointerup'); }); } // 滚动逻辑 scroll(deltaY) { const newScrollY = this.scrollY + deltaY; // 限制滚动范围 this.scrollY = Phaser.Math.Clamp(newScrollY, 0, this.maxScrollY); // 应用滚动 this.infoBarScrollContainer.setY(-this.scrollY); } // 更新滚动区域 updateScrollArea() { // 计算所有组件的总高度 let totalHeight = 20; // 顶部边距 const orderedComponents = this.getOrderedComponents(); orderedComponents.forEach(({id}) => { if (this.infoBarComponents[id]) { totalHeight += this.infoBarComponents[id].height + 10; // 组件高度 + 间距 } }); // 更新最大滚动距离 this.maxScrollY = Math.max(0, totalHeight - this.screenHeight + 20); // +20为底部边距 } // 切换信息栏显示/隐藏 toggleInfoBar() { this.infoBarVisible = !this.infoBarVisible; if (this.infoBarVisible) { // 展开信息栏 this.tweens.add({ targets: this.infoBarContainer, x: this.screenWidth - this.infoBarConfig.width, duration: 300, ease: 'Power1' }); this.infoBarToggle.setText('-'); // 创建所有启用的组件 this.createAllEnabledComponents(); } else { // 收起信息栏 this.tweens.add({ targets: this.infoBarContainer, x: this.screenWidth, duration: 300, ease: 'Power1' }); this.infoBarToggle.setText('+'); // 清理资源密集型组件 if (this.infoBarConfig.autoCleanup) { this.cleanupResourceIntensiveComponents(); } } } // 添加信息栏组件 addInfoBarComponent(id, componentConfig) { // 保存组件配置 this.infoBarConfig.components[id] = { enabled: componentConfig.enabled !== false, resourceIntensive: componentConfig.resourceIntensive || false, config: componentConfig }; // 如果信息栏可见且组件启用,则创建组件 if (this.infoBarVisible && this.infoBarConfig.components[id].enabled) { this.createComponentInstance(id, componentConfig); // 重新排列组件 this.rearrangeComponents(); } return this.infoBarComponents[id]; } // 创建组件实例 createComponentInstance(id, componentConfig) { // 根据组件类型创建不同的实例 let componentInstance; switch (componentConfig.type) { case 'text': componentInstance = this.createTextComponent(id, componentConfig); break; case 'miniMap': componentInstance = this.createMiniMapComponent(id, componentConfig); break; case 'placeholder': default: componentInstance = this.createPlaceholderComponent(id, componentConfig); break; } // 保存组件实例 this.infoBarComponents[id] = componentInstance; return componentInstance; } // 创建文本组件 createTextComponent(id, config) { const componentGroup = this.add.container( 10, // 相对于滚动容器的位置,左内边距10px 0 ); // 创建组件容器,用于容纳标题栏和内容 const componentContent = this.add.container(0, 0); // 创建标题栏背景 const titleBar = this.add.rectangle( 0, 0, this.infoBarConfig.width - 20, 30, 0x444444, 0.5 ).setOrigin(0, 0); // 创建组件标题 const title = this.add.text( 10, 5, config.title, { fontSize: '14px', fill: '#ffffff', fontWeight: 'bold' } ).setOrigin(0, 0); // 创建展开/收起按钮 const toggleBtn = this.add.text( this.infoBarConfig.width - 30, 5, '-', { fontSize: '16px', fill: '#ffffff' } ).setOrigin(0, 0).setInteractive(); // 创建分隔线 const separator = this.add.line( 0, 30, 0, 0, this.infoBarConfig.width - 20, 0, 0x555555 ).setOrigin(0, 0); // 创建内容容器,用于动态管理内容 const contentContainer = this.add.container(0, 30); // 创建内容文本 const contentTexts = []; config.content.forEach((line, index) => { const text = this.add.text( 10, index * 25, line, { fontSize: '12px', fill: '#cccccc' } ).setOrigin(0, 0); contentTexts.push(text); }); // 将内容添加到内容容器 contentContainer.add(contentTexts); // 添加所有元素到组件内容 componentContent.add([titleBar, title, toggleBtn, separator, contentContainer]); // 添加组件内容到组件组 componentGroup.add(componentContent); // 添加到滚动容器 this.infoBarScrollContainer.add(componentGroup); // 保存组件状态 const componentState = { expanded: true, contentVisible: true }; // 添加展开/收起点击事件 toggleBtn.on('pointerdown', () => { this.toggleComponent(id, componentState, contentContainer, toggleBtn); }); // 计算高度 const collapsedHeight = 40; const expandedHeight = config.height || (30 + config.content.length * 25) + 10; return { group: componentGroup, componentContent: componentContent, title: title, titleBar: titleBar, toggleBtn: toggleBtn, separator: separator, contentContainer: contentContainer, content: contentTexts, type: config.type, config: config, state: componentState, collapsedHeight: collapsedHeight, expandedHeight: expandedHeight, height: expandedHeight }; } // 创建小地图组件(示例) createMiniMapComponent(id, config) { const componentGroup = this.add.container( 10, // 相对于滚动容器的位置,左内边距10px 0 ); // 创建组件容器,用于容纳标题栏和内容 const componentContent = this.add.container(0, 0); // 创建标题栏背景 const titleBar = this.add.rectangle( 0, 0, this.infoBarConfig.width - 20, 30, 0x444444, 0.5 ).setOrigin(0, 0); // 创建组件标题 const title = this.add.text( 10, 5, config.title, { fontSize: '14px', fill: '#ffffff', fontWeight: 'bold' } ).setOrigin(0, 0); // 创建展开/收起按钮 const toggleBtn = this.add.text( this.infoBarConfig.width - 30, 5, '-', { fontSize: '16px', fill: '#ffffff' } ).setOrigin(0, 0).setInteractive(); // 创建分隔线 const separator = this.add.line( 0, 30, 0, 0, this.infoBarConfig.width - 20, 0, 0x555555 ).setOrigin(0, 0); // 创建内容容器,用于动态管理内容 const contentContainer = this.add.container(0, 30); // 创建小地图占位符(实际项目中替换为真实小地图) const miniMapBg = this.add.rectangle( (this.infoBarConfig.width - 20) / 2, (config.height - 40) / 2, // 垂直居中,减去标题栏高度 this.infoBarConfig.width - 40, // 宽度固定为信息栏宽度减去内边距 config.height - 50, // 高度固定,减去标题和分隔线高度 0x111111, 1 ).setOrigin(0.5, 0.5); const miniMapText = this.add.text( (this.infoBarConfig.width - 20) / 2, (config.height - 40) / 2, // 垂直居中 '小地图', { fontSize: '12px', fill: '#cccccc' } ).setOrigin(0.5, 0.5); // 将内容添加到内容容器 contentContainer.add([miniMapBg, miniMapText]); // 添加所有元素到组件内容 componentContent.add([titleBar, title, toggleBtn, separator, contentContainer]); // 添加组件内容到组件组 componentGroup.add(componentContent); // 添加到滚动容器 this.infoBarScrollContainer.add(componentGroup); // 保存组件状态 const componentState = { expanded: true, contentVisible: true, contentCreated: true // 标记内容已创建 }; // 添加展开/收起点击事件 toggleBtn.on('pointerdown', () => { this.toggleComponent(id, componentState, contentContainer, toggleBtn, true); }); // 计算高度 const collapsedHeight = 40; const expandedHeight = config.height || 160; return { group: componentGroup, componentContent: componentContent, title: title, titleBar: titleBar, toggleBtn: toggleBtn, separator: separator, contentContainer: contentContainer, map: miniMapBg, mapText: miniMapText, type: config.type, config: config, state: componentState, collapsedHeight: collapsedHeight, expandedHeight: expandedHeight, height: expandedHeight }; } // 创建占位符组件 createPlaceholderComponent(id, config) { const componentGroup = this.add.container( 10, // 相对于滚动容器的位置,左内边距10px 0 ); // 创建组件容器,用于容纳标题栏和内容 const componentContent = this.add.container(0, 0); // 创建标题栏背景 const titleBar = this.add.rectangle( 0, 0, this.infoBarConfig.width - 20, 30, 0x444444, 0.5 ).setOrigin(0, 0); // 创建组件标题 const title = this.add.text( 10, 5, config.title, { fontSize: '14px', fill: '#ffffff', fontWeight: 'bold' } ).setOrigin(0, 0); // 创建展开/收起按钮 const toggleBtn = this.add.text( this.infoBarConfig.width - 30, 5, '-', { fontSize: '16px', fill: '#ffffff' } ).setOrigin(0, 0).setInteractive(); // 创建分隔线 const separator = this.add.line( 0, 30, 0, 0, this.infoBarConfig.width - 20, 0, 0x555555 ).setOrigin(0, 0); // 创建内容容器,用于动态管理内容 const contentContainer = this.add.container(0, 30); // 创建内容 const contentText = this.add.text( 10, 0, config.content.join('\n'), { fontSize: '12px', fill: '#cccccc', wordWrap: { width: this.infoBarConfig.width - 40 } } ).setOrigin(0, 0); // 将内容添加到内容容器 contentContainer.add([contentText]); // 添加所有元素到组件内容 componentContent.add([titleBar, title, toggleBtn, separator, contentContainer]); // 添加组件内容到组件组 componentGroup.add(componentContent); // 添加到滚动容器 this.infoBarScrollContainer.add(componentGroup); // 保存组件状态 const componentState = { expanded: true, contentVisible: true }; // 添加展开/收起点击事件 toggleBtn.on('pointerdown', () => { this.toggleComponent(id, componentState, contentContainer, toggleBtn); }); // 计算高度 const collapsedHeight = 40; const expandedHeight = config.height || (50 + contentText.height) + 10; return { group: componentGroup, componentContent: componentContent, title: title, titleBar: titleBar, toggleBtn: toggleBtn, separator: separator, contentContainer: contentContainer, content: [contentText], type: config.type, config: config, state: componentState, collapsedHeight: collapsedHeight, expandedHeight: expandedHeight, height: expandedHeight }; } // 更新信息栏组件内容 updateInfoBarComponent(id, newContent) { const component = this.infoBarComponents[id]; if (component && component.type === 'text') { // 清空现有内容 component.content.forEach(text => text.destroy()); component.content = []; // 添加新内容 newContent.forEach((line, index) => { const text = this.add.text( 0, 30 + index * 25, line, { fontSize: '12px', fill: '#cccccc' } ).setOrigin(0, 0); component.group.add(text); component.content.push(text); }); // 重新排列组件(保持固定高度) this.rearrangeComponents(); } } // 重新排列组件 rearrangeComponents() { let currentY = 20; // 起始Y位置,顶部边距20px // 按自定义顺序排列组件 const orderedComponents = this.getOrderedComponents(); orderedComponents.forEach(({id}) => { const component = this.infoBarComponents[id]; if (component && component.group) { component.group.setY(currentY); currentY += component.height + 10; // 组件高度 + 间距10px } }); // 更新滚动区域 this.updateScrollArea(); } // 切换组件显示/隐藏 toggleInfoBarComponent(id) { const componentConfig = this.infoBarConfig.components[id]; if (componentConfig) { componentConfig.enabled = !componentConfig.enabled; if (componentConfig.enabled) { // 启用组件,创建实例 if (this.infoBarVisible) { this.createComponentInstance(id, componentConfig.config); this.rearrangeComponents(); } } else { // 禁用组件,销毁实例 this.destroyComponentInstance(id); this.rearrangeComponents(); } } } // 销毁组件实例 destroyComponentInstance(id) { if (this.infoBarComponents[id]) { this.infoBarComponents[id].group.destroy(); delete this.infoBarComponents[id]; } } // 清理资源密集型组件 cleanupResourceIntensiveComponents() { for (const id in this.infoBarConfig.components) { const componentConfig = this.infoBarConfig.components[id]; if (componentConfig.resourceIntensive && this.infoBarComponents[id]) { this.destroyComponentInstance(id); } } // 收起时重新排列剩余组件,确保位置正确 this.rearrangeComponents(); } // 重新创建资源密集型组件 recreateResourceIntensiveComponents() { for (const id in this.infoBarConfig.components) { const componentConfig = this.infoBarConfig.components[id]; if (componentConfig.resourceIntensive && componentConfig.enabled) { this.createComponentInstance(id, componentConfig.config); } } } // 切换信息栏显示/隐藏 toggleInfoBar() { this.infoBarVisible = !this.infoBarVisible; if (this.infoBarVisible) { // 展开信息栏 this.tweens.add({ targets: this.infoBarContainer, x: this.screenWidth - this.infoBarConfig.width, duration: 300, ease: 'Power1' }); this.infoBarToggle.setText('-'); // 只创建缺失的组件(主要是资源密集型组件) this.createMissingComponents(); // 确保所有组件正确排列 this.rearrangeComponents(); } else { // 收起信息栏 this.tweens.add({ targets: this.infoBarContainer, x: this.screenWidth, duration: 300, ease: 'Power1' }); this.infoBarToggle.setText('+'); // 只清理资源密集型组件 this.cleanupResourceIntensiveComponents(); } } // 创建缺失的组件 createMissingComponents() { const orderedComponents = this.getOrderedComponents(); orderedComponents.forEach(({id, config}) => { if (config.enabled && !this.infoBarComponents[id]) { this.createComponentInstance(id, config.config); } }); } // 创建所有启用的组件 createAllEnabledComponents() { // 先销毁所有现有组件,避免重叠 this.destroyAllComponents(); // 然后创建所有启用的组件 const orderedComponents = this.getOrderedComponents(); orderedComponents.forEach(({id, config}) => { if (config.enabled) { this.createComponentInstance(id, config.config); } }); // 排列组件 this.rearrangeComponents(); // 更新滚动区域 this.updateScrollArea(); } // 销毁所有组件 destroyAllComponents() { for (const id in this.infoBarComponents) { this.destroyComponentInstance(id); } } // 切换组件展开/收起 toggleComponent(id, state, contentContainer, toggleBtn, isResourceIntensive = false) { state.expanded = !state.expanded; if (state.expanded) { // 展开组件 toggleBtn.setText('-'); if (isResourceIntensive) { // 资源密集型组件,需要重新创建内容 if (!state.contentCreated) { this.recreateComponentContent(id); state.contentCreated = true; } } contentContainer.visible = true; // 更新组件高度 this.infoBarComponents[id].height = this.infoBarComponents[id].expandedHeight; } else { // 收起组件 toggleBtn.setText('+'); if (isResourceIntensive) { // 资源密集型组件,清理内容 this.destroyComponentContent(id); state.contentCreated = false; } contentContainer.visible = false; // 更新组件高度 this.infoBarComponents[id].height = this.infoBarComponents[id].collapsedHeight; } // 重新排列所有组件 this.rearrangeComponents(); // 更新滚动区域 this.updateScrollArea(); } // 销毁组件内容 destroyComponentContent(id) { const component = this.infoBarComponents[id]; if (component && component.contentContainer) { // 销毁内容容器中的所有子元素 component.contentContainer.removeAll(true); } } // 重新创建组件内容 recreateComponentContent(id) { const component = this.infoBarComponents[id]; if (!component || !component.contentContainer) return; const config = component.config; switch (config.type) { case 'miniMap': case 'placeholder': // 重新创建小地图内容 const miniMapBg = this.add.rectangle( (this.infoBarConfig.width - 20) / 2, (config.height - 40) / 2, this.infoBarConfig.width - 40, config.height - 50, 0x111111, 1 ).setOrigin(0.5, 0.5); const miniMapText = this.add.text( (this.infoBarConfig.width - 20) / 2, (config.height - 40) / 2, '小地图', { fontSize: '12px', fill: '#cccccc' } ).setOrigin(0.5, 0.5); component.contentContainer.add([miniMapBg, miniMapText]); component.map = miniMapBg; component.mapText = miniMapText; break; case 'text': // 重新创建文本内容 const contentTexts = []; config.content.forEach((line, index) => { const text = this.add.text( 10, index * 25, line, { fontSize: '12px', fill: '#cccccc' } ).setOrigin(0, 0); contentTexts.push(text); }); component.contentContainer.add(contentTexts); component.content = contentTexts; break; } } // 设置信息栏自动清理策略 setInfoBarAutoCleanup(enabled) { this.infoBarConfig.autoCleanup = enabled; } // 更新信息栏内容的方法(向后兼容) updateInfoBarContent(newContent) { // 兼容旧接口,更新第一个文本组件 const firstTextComponentId = Object.keys(this.infoBarComponents).find( id => this.infoBarComponents[id] && this.infoBarComponents[id].type === 'text' ); if (firstTextComponentId) { this.updateInfoBarComponent(firstTextComponentId, newContent); } } update() { // 示例:模拟动态更新角色状态 if (this.infoBarVisible && this.infoBarComponents.playerStats) { // 这里可以添加真实的状态更新逻辑 } } }