diff --git a/c.zip b/c.zip new file mode 100644 index 0000000..b65f903 Binary files /dev/null and b/c.zip differ diff --git a/items/Item.js b/items/Item.js index eb896ea..e7748ad 100644 --- a/items/Item.js +++ b/items/Item.js @@ -150,13 +150,21 @@ export default class Item extends Phaser.GameObjects.Sprite { * @param {Object} user - 使用物品的单位 */ useFromInventory(user) { + // 从用户对象中获取场景引用 + if (user && user.scene) { + this.scene = user.scene; + } // 使用物品 this.use(user); - - // 从背包中移除物品 - if (user.inventory) { - user.inventory.removeItem(this.id); - } + // 注意:物品的具体使用方法(如useSeed)中已经处理了从背包移除的逻辑 + } + + /** + * 设置物品的场景引用 + * @param {Object} scene - 场景对象 + */ + setScene(scene) { + this.scene = scene; } /** @@ -210,16 +218,14 @@ export default class Item extends Phaser.GameObjects.Sprite { console.log('DEBUG: 触发 plant-seed 事件'); this.scene.events.emit('plant-seed', this, user); - // 从背包中移除种子 - if (user.inventory) { - console.log(`DEBUG: 从背包中移除种子 ${this.id}`); - user.inventory.removeItem(this.id); - } + // 注意:不立即从背包中移除种子,而是在实际种植时移除 + // 这样用户可以取消种植而不会失去种子 // 显示种植提示 this.scene.events.emit('show-message', `准备种植 ${this.name}`); } else { - console.log('DEBUG: 种子不可种植'); + console.log(`DEBUG: ${this.name} 不可种植`); + this.scene.events.emit('show-message', `${this.name} 不可种植`); } } diff --git a/objects/Crop.js b/objects/Crop.js index fa3c3dc..1e3d732 100644 --- a/objects/Crop.js +++ b/objects/Crop.js @@ -126,13 +126,11 @@ export default class Crop extends Phaser.GameObjects.Sprite { * 作物被点击时的处理函数 */ onCropClicked() { - if (this.isHarvestable) { - this.harvest(); - } else { - // 显示生长进度 - const growthProgress = Math.min(100, Math.floor(((Date.now() - this.plantedTime) / this.growthTime) * 100)); - this.scene.events.emit('show-message', `作物正在生长中: ${growthProgress}%`); - } + // 调用场景的显示作物详情方法 + this.scene.showCropDetails(this); + + // 阻止事件冒泡,防止触发角色移动 + return false; } /** diff --git a/scenes/BootScene.js b/scenes/BootScene.js index a83a84d..2ed5391 100644 --- a/scenes/BootScene.js +++ b/scenes/BootScene.js @@ -11,11 +11,12 @@ export default class BootScene extends Phaser.Scene { this.cameras.main.setBackgroundColor('#000000'); // 添加标题文本 - this.add.text(this.sys.game.config.width / 2, 100, '测试场景菜单', { + const title = this.add.text(this.sys.game.config.width / 2, 50, '测试场景菜单', { fontSize: '32px', fill: '#ffffff', fontFamily: 'Arial' }).setOrigin(0.5, 0.5); + title.setScrollFactor(0); // 固定标题,不随滚动移动 // 测试场景列表 const testScenes = [ @@ -36,17 +37,46 @@ export default class BootScene extends Phaser.Scene { { key: 'GameScene', name: '返回主游戏场景' } ]; - // 创建按钮网格 - const buttonWidth = 400; - const buttonHeight = 50; - const buttonSpacing = 20; - const startY = 200; + // 滚动容器配置 + const containerWidth = this.sys.game.config.width - 40; + const containerHeight = this.sys.game.config.height - 150; + const containerX = 20; + const containerY = 100; + + // 创建滚动容器背景 + const scrollBackground = this.add.rectangle( + this.sys.game.config.width / 2, + containerY + containerHeight / 2, + containerWidth, + containerHeight, + 0x111111, + 0.5 + ); + scrollBackground.setOrigin(0.5, 0.5); + scrollBackground.setScrollFactor(0); // 固定背景,不随滚动移动 + // 创建滚动容器 + this.scrollContainer = this.add.container(containerX, containerY); + + // 按钮配置 + const columns = 2; // 2列布局 + const buttonWidth = (containerWidth - 30) / columns; // 两列按钮,留出间距 + const buttonHeight = 50; + const buttonSpacing = 20; // 按钮间距 + const columnSpacing = 10; // 列间距 + + // 创建按钮 testScenes.forEach((scene, index) => { + // 计算按钮位置(2列布局) + const col = index % columns; + const row = Math.floor(index / columns); + const x = col * (buttonWidth + columnSpacing); + const y = row * (buttonHeight + buttonSpacing); + // 创建按钮背景 const button = this.add.rectangle( - this.sys.game.config.width / 2, - startY + index * (buttonHeight + buttonSpacing), + x + buttonWidth / 2, + y + buttonHeight / 2, buttonWidth, buttonHeight, 0x333333 @@ -54,15 +84,16 @@ export default class BootScene extends Phaser.Scene { // 添加按钮文本 const text = this.add.text( - this.sys.game.config.width / 2, - startY + index * (buttonHeight + buttonSpacing), + x + buttonWidth / 2, + y + buttonHeight / 2, scene.name, { - fontSize: '18px', + fontSize: '16px', fill: '#ffffff', fontFamily: 'Arial' } ).setOrigin(0.5, 0.5); + text.setWordWrapWidth(buttonWidth - 20); // 文本自动换行 // 使按钮可交互 button.setInteractive({ @@ -82,6 +113,93 @@ export default class BootScene extends Phaser.Scene { button.on('pointerout', () => { button.setFillStyle(0x333333); }); + + // 将按钮和文本添加到滚动容器 + this.scrollContainer.add(button); + this.scrollContainer.add(text); + }); + + // 计算滚动容器的实际高度 + const rows = Math.ceil(testScenes.length / columns); + const contentHeight = rows * (buttonHeight + buttonSpacing); + + // 添加滚动功能 + this.setupScrolling(contentHeight, containerHeight); + + // 添加滚动提示 + const scrollHint = this.add.text( + this.sys.game.config.width / 2, + this.sys.game.config.height - 30, + '鼠标滚轮或触摸滑动滚动', + { + fontSize: '14px', + fill: '#aaaaaa', + fontFamily: 'Arial' + } + ).setOrigin(0.5, 0.5); + scrollHint.setScrollFactor(0); // 固定提示,不随滚动移动 + } + + /** + * 设置滚动功能 + * @param {number} contentHeight - 内容高度 + * @param {number} containerHeight - 容器高度 + */ + setupScrolling(contentHeight, containerHeight) { + // 只有当内容高度大于容器高度时才添加滚动 + if (contentHeight <= containerHeight) { + return; + } + + // 滚动位置 + this.scrollY = 0; + // 最大滚动位置 + this.maxScrollY = contentHeight - containerHeight; + + // 添加鼠标滚轮事件 + this.input.on('wheel', (pointer, gameObjects, deltaX, deltaY, deltaZ) => { + // 计算新的滚动位置 + this.scrollY += deltaY * 0.5; // 调整滚动速度 + + // 限制滚动范围 + this.scrollY = Math.max(0, Math.min(this.scrollY, this.maxScrollY)); + + // 应用滚动 + this.scrollContainer.setPosition(this.scrollContainer.x, this.scrollContainer.y - this.scrollContainer.list[0].y + this.scrollY); + }); + + // 添加触摸滚动支持 + let isDragging = false; + let lastY = 0; + + this.input.on('pointerdown', (pointer) => { + isDragging = true; + lastY = pointer.y; + }); + + this.input.on('pointermove', (pointer) => { + if (isDragging) { + const deltaY = pointer.y - lastY; + + // 计算新的滚动位置 + this.scrollY -= deltaY * 0.5; // 调整滚动速度 + + // 限制滚动范围 + this.scrollY = Math.max(0, Math.min(this.scrollY, this.maxScrollY)); + + // 应用滚动 + this.scrollContainer.setPosition(this.scrollContainer.x, this.scrollContainer.y - this.scrollContainer.list[0].y + this.scrollY); + + lastY = pointer.y; + } + }); + + this.input.on('pointerup', () => { + isDragging = false; + }); + + this.input.on('pointerout', () => { + isDragging = false; }); } } diff --git a/scenes/testScenes/AutoMovementTestScene.js b/scenes/testScenes/AutoMovementTestScene.js index d3bf4ef..8a6c4fe 100644 --- a/scenes/testScenes/AutoMovementTestScene.js +++ b/scenes/testScenes/AutoMovementTestScene.js @@ -4,9 +4,9 @@ import { InputSystem } from '../../systems/InputSystem.js'; import { SelectionSystem } from '../../systems/SelectionSystem.js'; import { CommandSystem } from '../../systems/CommandSystem.js'; -export default class MovementTestScene5 extends Phaser.Scene { +export default class AutoMovementTestScene extends Phaser.Scene { constructor() { - super({ key: 'MovementTestScene5' }); + super({ key: 'AutoMovementTestScene' }); } create() { @@ -108,6 +108,43 @@ export default class MovementTestScene5 extends Phaser.Scene { this.input.keyboard.on('keydown-SPACE', () => { this.scene.start('BootScene'); }); + + // 添加返回菜单按钮 + this.createReturnButton(); + } + + /** + * 创建返回菜单按钮 + */ + createReturnButton() { + // 创建按钮背景 + const button = this.add.rectangle(10, 130, 150, 40, 0x333333); + button.setOrigin(0, 0); + button.setScrollFactor(0, 0); + button.setDepth(10); + button.setInteractive({ useHandCursor: true }); + + // 按钮文本 + const buttonText = this.add.text(25, 140, '返回菜单', { + fontSize: '16px', + fill: '#ffffff', + fontFamily: 'Arial' + }); + buttonText.setScrollFactor(0, 0); + buttonText.setDepth(11); + + // 按钮事件 + button.on('pointerdown', () => { + this.scene.start('BootScene'); + }); + + button.on('pointerover', () => { + button.setFillStyle(0x555555); + }); + + button.on('pointerout', () => { + button.setFillStyle(0x333333); + }); } update() { diff --git a/scenes/testScenes/FarmingTestScene.js b/scenes/testScenes/FarmingTestScene.js index 8babd08..072f1ff 100644 --- a/scenes/testScenes/FarmingTestScene.js +++ b/scenes/testScenes/FarmingTestScene.js @@ -213,28 +213,38 @@ export default class FarmingTestScene extends Phaser.Scene { this.inventoryUI.toggle(); }); + // 使用物品快捷键(Q键) + this.input.keyboard.on('keydown-Q', () => { + console.log('DEBUG: Q键被按下,尝试使用选中的物品'); + if (this.inventoryUI && this.inventoryUI.selectedItem) { + console.log('DEBUG: 有选中的物品,调用useItem方法'); + this.inventoryUI.useItem(this.inventoryUI.selectedItem); + } + }); + // 空格键返回启动场景 this.input.keyboard.on('keydown-SPACE', () => { console.log('DEBUG: 空格键被按下,返回启动场景'); this.scene.start('BootScene'); }); - // 鼠标左键点击地面种植作物 + // 鼠标点击处理 this.input.on('pointerdown', (pointer) => { console.log(`DEBUG: 鼠标点击事件触发,按键: ${pointer.button}, 位置: x=${pointer.x}, y=${pointer.y}`); console.log(`DEBUG: 当前种植模式状态: isPlantingMode=${this.isPlantingMode}, selectedSeed=${this.selectedSeed ? this.selectedSeed.name : 'null'}`); - if (this.isPlantingMode && this.selectedSeed) { - console.log('DEBUG: 满足种植条件,调用 plantSeedAt 方法'); - this.plantSeedAt(pointer); - } - }); - - // 鼠标右键取消种植模式 - this.input.on('pointerdown', (pointer) => { + // 检查点击位置是否在UI元素上(背包UI或侧边栏) + const isUIClick = this.isPointInUI(pointer); + console.log(`DEBUG: 是否点击在UI元素上: ${isUIClick}`); + if (pointer.rightButtonDown()) { + // 右键点击取消种植模式 console.log('DEBUG: 鼠标右键点击,取消种植模式'); this.cancelPlantingMode(); + } else if (this.isPlantingMode && this.selectedSeed && !isUIClick) { + // 左键点击地面种植作物,确保不是点击UI元素 + console.log('DEBUG: 满足种植条件且不是UI点击,调用 plantSeedAt 方法'); + this.plantSeedAt(pointer); } }); @@ -249,14 +259,30 @@ export default class FarmingTestScene extends Phaser.Scene { createButtons() { const buttonWidth = 200; const buttonHeight = 40; - const buttonY = this.sys.game.config.height - 100; + const buttonY = this.sys.game.config.height - 150; + + // 创建拾取物品按钮 + this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY - 50, '拾取物品(F)', () => { + // 调用与F键相同的拾取功能 + this.inputSystem.handleQuickPickup(); + }); + + // 创建背包按钮 + this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY, '打开/关闭背包', () => { + this.inventoryUI.toggle(); + }); // 创建随机物品按钮 - this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY, '创建随机种子', () => { + this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY + 50, '创建随机种子', () => { const seedTypes = ['wheat_seed', 'carrot_seed']; const randomSeedType = seedTypes[Math.floor(Math.random() * seedTypes.length)]; this.itemManager.createItem(randomSeedType, this.player.x + 50, this.player.y); }); + + // 创建返回菜单按钮 + this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY + 100, '返回菜单', () => { + this.scene.start('BootScene'); + }); } /** @@ -312,8 +338,8 @@ export default class FarmingTestScene extends Phaser.Scene { // 显示种植光标,初始位置设置为当前鼠标位置 console.log(`DEBUG: 当前鼠标位置: x=${this.input.mousePointer.x}, y=${this.input.mousePointer.y}`); - this.plantingCursor = this.add.text(this.input.mousePointer.x, this.input.mousePointer.y, '🌱', { - fontSize: '24px' + this.plantingCursor = this.add.text(this.input.mousePointer.x, this.input.mousePointer.y, '🌱', { + fontSize: '24px' }); console.log(`DEBUG: 种植光标创建结果: ${this.plantingCursor ? '成功' : '失败'}`); @@ -330,12 +356,22 @@ export default class FarmingTestScene extends Phaser.Scene { // 跟随鼠标移动 - 使用命名的事件监听器,方便后续移除 this.mouseMoveListener = (pointer) => { console.log(`DEBUG: 鼠标移动事件触发,指针位置: x=${pointer.x}, y=${pointer.y}`); - scene.plantingCursor.setPosition(pointer.x, pointer.y); + // 检查种植光标是否存在,避免null引用错误 + if (scene.plantingCursor) { + scene.plantingCursor.setPosition(pointer.x, pointer.y); + } }; // 添加鼠标移动事件监听 console.log('DEBUG: 添加鼠标移动事件监听'); this.input.on('pointermove', this.mouseMoveListener); + + // 更新背包UI,切换到取消种植按钮 + if (this.inventoryUI) { + console.log('DEBUG: 更新背包UI,切换到取消种植按钮'); + this.inventoryUI.updatePlantButtonState(true); + } + console.log('DEBUG: 种植模式启动完成'); } @@ -367,6 +403,15 @@ export default class FarmingTestScene extends Phaser.Scene { console.log(`DEBUG: 鼠标移动监听器移除结果: ${this.mouseMoveListener ? '失败' : '成功'}`); } + // 更新背包UI,切换回种植按钮 + if (this.inventoryUI) { + console.log('DEBUG: 更新背包UI,切换回种植按钮'); + this.inventoryUI.updatePlantButtonState(false); + // 取消背包中选中的物品,保持UI一致性 + console.log('DEBUG: 取消背包中选中的物品'); + this.inventoryUI.deselectItem(); + } + console.log('DEBUG: 种植模式取消完成'); } @@ -376,6 +421,29 @@ export default class FarmingTestScene extends Phaser.Scene { plantSeedAt(pointer) { console.log('DEBUG: plantSeedAt 方法被调用'); + // 检查背包中是否还有该种子 + let seedItem = null; + if (this.player.inventory) { + // 查找背包中是否还有该类型的种子 + const allItems = this.player.inventory.getAllItems(); + if (allItems instanceof Map) { + allItems.forEach(item => { + if (item.itemTypeId === this.selectedSeed.itemTypeId) { + seedItem = item; + } + }); + } else { + seedItem = allItems.find(item => item.itemTypeId === this.selectedSeed.itemTypeId); + } + } + + if (!seedItem) { + console.log('DEBUG: 背包中没有该种子,取消种植'); + this.showMessage(`背包中没有 ${this.selectedSeed.name},无法种植`); + this.cancelPlantingMode(); + return; + } + // 将屏幕坐标转换为世界坐标 const worldPoint = this.cameras.main.getWorldPoint(pointer.x, pointer.y); console.log(`DEBUG: 屏幕坐标转世界坐标: 屏幕(${pointer.x},${pointer.y}) -> 世界(${worldPoint.x},${worldPoint.y})`); @@ -393,13 +461,26 @@ export default class FarmingTestScene extends Phaser.Scene { console.log(`DEBUG: 作物创建结果: ${crop ? '成功' : '失败'}`); - // 添加到作物组 - this.cropGroup.add(crop); - console.log(`DEBUG: 作物已添加到作物组,当前作物数量: ${this.cropGroup.getLength()}`); - - // 显示种植成功消息 - this.showMessage(`已种植 ${this.selectedSeed.name}`); - console.log(`DEBUG: 显示种植成功消息: 已种植 ${this.selectedSeed.name}`); + if (crop) { + // 从背包中移除种子 + if (this.player.inventory) { + console.log(`DEBUG: 从背包中移除种子 ${seedItem.id}`); + this.player.inventory.removeItem(seedItem.id); + // 更新背包UI + this.inventoryUI.updateUI(); + } + + // 添加到作物组 + this.cropGroup.add(crop); + console.log(`DEBUG: 作物已添加到作物组,当前作物数量: ${this.cropGroup.getLength()}`); + + // 显示种植成功消息 + this.showMessage(`已种植 ${this.selectedSeed.name}`); + console.log(`DEBUG: 显示种植成功消息: 已种植 ${this.selectedSeed.name}`); + } else { + console.log('DEBUG: 作物创建失败'); + this.showMessage(`种植 ${this.selectedSeed.name} 失败`); + } // 取消种植模式 this.cancelPlantingMode(); @@ -429,6 +510,10 @@ export default class FarmingTestScene extends Phaser.Scene { } } } + + // 销毁作物对象 + crop.destroy(); + console.log('DEBUG: 作物已销毁'); } /** @@ -601,6 +686,193 @@ export default class FarmingTestScene extends Phaser.Scene { this.unitStatusText.setText(statusText); } + /** + * 检查点击位置是否在UI元素上 + * @param {Phaser.Input.Pointer} pointer - 指针对象 + * @returns {boolean} 是否点击在UI元素上 + */ + isPointInUI(pointer) { + // 检查是否点击在背包UI上 + if (this.inventoryUI && this.inventoryUI.isOpen) { + const uiRect = this.inventoryUI.container.getBounds(); + if (Phaser.Geom.Rectangle.Contains(uiRect, pointer.x - this.inventoryUI.container.x, pointer.y - this.inventoryUI.container.y)) { + return true; + } + } + + // 检查是否点击在侧边栏上 + if (this.sidebar) { + const sidebarRect = this.sidebar.getBounds(); + if (Phaser.Geom.Rectangle.Contains(sidebarRect, pointer.x, pointer.y)) { + return true; + } + } + + // 检查是否点击在物品信息面板上 + if (this.inventoryUI && this.inventoryUI.itemInfoPanel) { + const infoRect = this.inventoryUI.itemInfoPanel.getBounds(); + if (Phaser.Geom.Rectangle.Contains(infoRect, pointer.x, pointer.y)) { + return true; + } + } + + // 检查是否点击在作物详情面板上 + if (this.cropDetailsPanel) { + const detailsRect = this.cropDetailsPanel.getBounds(); + if (Phaser.Geom.Rectangle.Contains(detailsRect, pointer.x, pointer.y)) { + return true; + } + } + + // 检查是否点击在交互按钮上(返回菜单按钮等) + // 这里可以添加按钮的点击区域检查 + + return false; + } + + /** + * 显示作物详情信息 + * @param {Crop} crop - 作物对象 + */ + showCropDetails(crop) { + console.log('DEBUG: showCropDetails 方法被调用'); + + // 销毁之前的作物详情面板 + this.hideCropDetails(); + + // 创建作物详情面板 + const panelWidth = 250; + const panelHeight = 150; + const panelX = this.sys.game.config.width - panelWidth - 20; + const panelY = 100; + + this.cropDetailsPanel = this.add.rectangle( + panelX, + panelY, + panelWidth, + panelHeight, + 0x000000, + 0.8 + ); + this.cropDetailsPanel.setOrigin(0, 0); + this.cropDetailsPanel.setStrokeStyle(2, 0x4CAF50); + this.cropDetailsPanel.setDepth(200); + this.cropDetailsPanel.setScrollFactor(0, 0); + + // 阻止事件冒泡 + this.cropDetailsPanel.setInteractive(); + this.cropDetailsPanel.on('pointerdown', (pointer) => { + return false; + }); + + // 作物信息文本 + const cropInfo = crop.getInfo(); + const growthProgress = Math.min(100, Math.floor(((Date.now() - cropInfo.plantedTime) / cropInfo.growthTime) * 100)); + const stageNames = ['种子', '幼苗', '成长中', '成熟']; + + let detailsText = `${cropInfo.type} 作物\n`; + detailsText += `生长阶段: ${stageNames[cropInfo.growthStage]}\n`; + detailsText += `生长进度: ${growthProgress}%\n`; + detailsText += `可收获: ${cropInfo.isHarvestable ? '是' : '否'}`; + + this.cropDetailsText = this.add.text( + panelX + 10, + panelY + 10, + detailsText, + { font: '14px Arial', fill: '#ffffff', wordWrap: { width: panelWidth - 20 } } + ); + this.cropDetailsText.setDepth(210); + this.cropDetailsText.setScrollFactor(0, 0); + + // 如果作物可收获,添加收获按钮 + if (cropInfo.isHarvestable) { + this.harvestButton = this.add.text( + panelX + 10, + panelY + 100, + '[收获作物]', + { font: '14px Arial', fill: '#00ff00' } + ); + this.harvestButton.setDepth(210); + this.harvestButton.setScrollFactor(0, 0); + this.harvestButton.setInteractive({ + useHandCursor: true, + cursor: 'pointer' + }); + + // 绑定收获按钮事件 + this.harvestButton.on('pointerdown', (pointer) => { + console.log('DEBUG: 点击收获按钮'); + this.harvestCrop(crop); + this.hideCropDetails(); + return false; // 阻止事件冒泡,防止触发角色移动 + }); + + this.harvestButton.on('pointerover', (pointer) => { + this.harvestButton.setFill('#ffff00'); + return false; + }); + + this.harvestButton.on('pointerout', (pointer) => { + this.harvestButton.setFill('#00ff00'); + return false; + }); + } + + // 添加关闭按钮 + this.closeCropDetailsButton = this.add.text( + panelX + panelWidth - 25, + panelY + 5, + 'X', + { font: '18px Arial', fill: '#ffffff' } + ); + this.closeCropDetailsButton.setDepth(210); + this.closeCropDetailsButton.setScrollFactor(0, 0); + this.closeCropDetailsButton.setInteractive({ + useHandCursor: true, + cursor: 'pointer' + }); + + this.closeCropDetailsButton.on('pointerdown', (pointer) => { + this.hideCropDetails(); + return false; + }); + + this.closeCropDetailsButton.on('pointerover', (pointer) => { + this.closeCropDetailsButton.setFill('#ff0000'); + return false; + }); + + this.closeCropDetailsButton.on('pointerout', (pointer) => { + this.closeCropDetailsButton.setFill('#ffffff'); + return false; + }); + } + + /** + * 隐藏作物详情信息 + */ + hideCropDetails() { + if (this.cropDetailsPanel) { + this.cropDetailsPanel.destroy(); + this.cropDetailsPanel = null; + } + + if (this.cropDetailsText) { + this.cropDetailsText.destroy(); + this.cropDetailsText = null; + } + + if (this.harvestButton) { + this.harvestButton.destroy(); + this.harvestButton = null; + } + + if (this.closeCropDetailsButton) { + this.closeCropDetailsButton.destroy(); + this.closeCropDetailsButton = null; + } + } + /** * 显示消息 */ diff --git a/scenes/testScenes/InventoryTestScene.js b/scenes/testScenes/InventoryTestScene.js index 3349df2..f25d3e2 100644 --- a/scenes/testScenes/InventoryTestScene.js +++ b/scenes/testScenes/InventoryTestScene.js @@ -223,18 +223,28 @@ export default class InventoryTestScene extends Phaser.Scene { createButtons() { const buttonWidth = 200; const buttonHeight = 40; - const buttonY = this.sys.game.config.height - 100; + const buttonY = this.sys.game.config.height - 150; + + // 创建背包按钮 + this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY, '打开/关闭背包', () => { + this.inventoryUI.toggle(); + }); // 创建随机物品按钮 - this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY, '创建随机物品', () => { + this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY + 50, '创建随机物品', () => { this.itemManager.createRandomItem(); }); // 创建清理物品按钮 - this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY + 50, '清理所有物品', () => { + this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY + 100, '清理所有物品', () => { this.itemManager.clearAllItems(); this.itemInfoText.setText('所有物品已清理'); }); + + // 创建返回菜单按钮 + this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY + 150, '返回菜单', () => { + this.scene.start('BootScene'); + }); } /** diff --git a/scenes/testScenes/ItemListTestScene.js b/scenes/testScenes/ItemListTestScene.js index 570409d..8a2f93e 100644 --- a/scenes/testScenes/ItemListTestScene.js +++ b/scenes/testScenes/ItemListTestScene.js @@ -253,15 +253,20 @@ export default class ItemListTestScene extends Phaser.Scene { createButtons() { const buttonWidth = 200; const buttonHeight = 40; - const buttonY = this.sys.game.config.height - 100; + const buttonY = this.sys.game.config.height - 150; + + // 创建背包按钮 + this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY, '打开/关闭背包', () => { + this.inventoryUI.toggle(); + }); // 创建随机物品按钮 - this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY, '创建随机物品', () => { + this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY + 50, '创建随机物品', () => { this.itemManager.createRandomItem(); }); // 创建清理物品按钮 - this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY + 50, '清理所有物品', () => { + this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY + 100, '清理所有物品', () => { this.itemManager.clearAllItems(); this.itemInfoText.setText('所有物品已清理'); // 更新物品列表UI @@ -269,6 +274,11 @@ export default class ItemListTestScene extends Phaser.Scene { this.itemListUI.updateItems(this.player, this.itemManager.getActiveItems()); } }); + + // 创建返回菜单按钮 + this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY + 150, '返回菜单', () => { + this.scene.start('BootScene'); + }); } /** diff --git a/scenes/testScenes/ItemTestScene.js b/scenes/testScenes/ItemTestScene.js index 8e2cb7f..fa60a56 100644 --- a/scenes/testScenes/ItemTestScene.js +++ b/scenes/testScenes/ItemTestScene.js @@ -153,35 +153,58 @@ export default class ItemTestScene extends Phaser.Scene { }); this.input.keyboard.on('keydown-TWO', () => { - // 在单位附近创建食物类物品 - const x = unit.x + Phaser.Math.Between(-100, 100); - const y = unit.y + Phaser.Math.Between(-100, 100); - this.itemManager.createItemByType('food', x, y); + this.itemManager.createItem('wheat_seed', 0, 0); }); this.input.keyboard.on('keydown-THREE', () => { - // 在单位附近创建工具类物品 - const x = unit.x + Phaser.Math.Between(-100, 100); - const y = unit.y + Phaser.Math.Between(-100, 100); - this.itemManager.createItemByType('tool', x, y); + this.itemManager.createItem('wooden_sword', 0, 0); }); this.input.keyboard.on('keydown-FOUR', () => { + // 清理所有物品 this.itemManager.clearAllItems(); - this.itemInfoText.setText('所有物品已清理'); }); this.input.keyboard.on('keydown-SPACE', () => { this.scene.start('BootScene'); }); - // 监听物品点击事件 - this.events.on('item-clicked', (item) => { - this.showItemInfo(item); + // 添加返回菜单按钮 + this.createReturnButton(); + } + + /** + * 创建返回菜单按钮 + */ + createReturnButton() { + // 创建按钮背景 + const button = this.add.rectangle(10, 250, 150, 40, 0x333333); + button.setOrigin(0, 0); + button.setScrollFactor(0, 0); + button.setDepth(10); + button.setInteractive({ useHandCursor: true }); + + // 按钮文本 + const buttonText = this.add.text(25, 260, '返回菜单', { + fontSize: '16px', + fill: '#ffffff', + fontFamily: 'Arial' + }); + buttonText.setScrollFactor(0, 0); + buttonText.setDepth(11); + + // 按钮事件 + button.on('pointerdown', () => { + this.scene.start('BootScene'); }); - // 创建一些交互按钮 - this.createButtons(); + button.on('pointerover', () => { + button.setFillStyle(0x555555); + }); + + button.on('pointerout', () => { + button.setFillStyle(0x333333); + }); } /** diff --git a/scenes/testScenes/JoystickMovementTestScene.js b/scenes/testScenes/JoystickMovementTestScene.js index b71a0f4..7cc02dd 100644 --- a/scenes/testScenes/JoystickMovementTestScene.js +++ b/scenes/testScenes/JoystickMovementTestScene.js @@ -80,6 +80,43 @@ export default class JoystickMovementTestScene extends Phaser.Scene { this.input.keyboard.on('keydown-SPACE', () => { this.scene.start('BootScene'); }); + + // 添加返回菜单按钮 + this.createReturnButton(); + } + + /** + * 创建返回菜单按钮 + */ + createReturnButton() { + // 创建按钮背景 + const button = this.add.rectangle(10, 100, 150, 40, 0x333333); + button.setOrigin(0, 0); + button.setScrollFactor(0, 0); + button.setDepth(10); + button.setInteractive({ useHandCursor: true }); + + // 按钮文本 + const buttonText = this.add.text(25, 110, '返回菜单', { + fontSize: '16px', + fill: '#ffffff', + fontFamily: 'Arial' + }); + buttonText.setScrollFactor(0, 0); + buttonText.setDepth(11); + + // 按钮事件 + button.on('pointerdown', () => { + this.scene.start('BootScene'); + }); + + button.on('pointerover', () => { + button.setFillStyle(0x555555); + }); + + button.on('pointerout', () => { + button.setFillStyle(0x333333); + }); } update() { diff --git a/scenes/testScenes/KeyboardMovementTestScene.js b/scenes/testScenes/KeyboardMovementTestScene.js index 1f7b032..b589d0b 100644 --- a/scenes/testScenes/KeyboardMovementTestScene.js +++ b/scenes/testScenes/KeyboardMovementTestScene.js @@ -78,6 +78,43 @@ export default class KeyboardMovementTestScene extends Phaser.Scene { this.input.keyboard.on('keydown-SPACE', () => { this.scene.start('BootScene'); }); + + // 添加返回菜单按钮 + this.createReturnButton(); + } + + /** + * 创建返回菜单按钮 + */ + createReturnButton() { + // 创建按钮背景 + const button = this.add.rectangle(10, 100, 150, 40, 0x333333); + button.setOrigin(0, 0); + button.setScrollFactor(0, 0); + button.setDepth(10); + button.setInteractive({ useHandCursor: true }); + + // 按钮文本 + const buttonText = this.add.text(25, 110, '返回菜单', { + fontSize: '16px', + fill: '#ffffff', + fontFamily: 'Arial' + }); + buttonText.setScrollFactor(0, 0); + buttonText.setDepth(11); + + // 按钮事件 + button.on('pointerdown', () => { + this.scene.start('BootScene'); + }); + + button.on('pointerover', () => { + button.setFillStyle(0x555555); + }); + + button.on('pointerout', () => { + button.setFillStyle(0x333333); + }); } update() { diff --git a/scenes/testScenes/MapEditSinglePicTestScene.js b/scenes/testScenes/MapEditSinglePicTestScene.js index 89c9dc4..c96ffeb 100644 --- a/scenes/testScenes/MapEditSinglePicTestScene.js +++ b/scenes/testScenes/MapEditSinglePicTestScene.js @@ -291,6 +291,11 @@ export default class MapEditSinglePicTestScene extends Phaser.Scene { this.createButton(this.sys.game.config.width - 200, 130, 180, 30, '加载地图', () => { this.loadMap(); }); + + // 返回启动场景按钮 + this.createButton(this.sys.game.config.width - 200, 170, 180, 30, '返回菜单', () => { + this.scene.start('BootScene'); + }); } /** diff --git a/scenes/testScenes/MapEditTestScene.js b/scenes/testScenes/MapEditTestScene.js index b248f33..e9b7096 100644 --- a/scenes/testScenes/MapEditTestScene.js +++ b/scenes/testScenes/MapEditTestScene.js @@ -494,6 +494,46 @@ export default class MapEditTestScene extends Phaser.Scene { this.terrainModeButton.on('pointerdown', () => { this.toggleTerrainMode(); }); + + // 添加返回菜单按钮 + this.createReturnButton(); + } + + /** + * 创建返回菜单按钮 + */ + createReturnButton() { + const buttonX = 10; + const buttonY = this.sys.game.config.height - 50; + + // 创建按钮背景 + const button = this.add.rectangle(buttonX, buttonY, 150, 40, 0x333333); + button.setOrigin(0, 0); + button.setScrollFactor(0, 0); + button.setDepth(100); + button.setInteractive({ useHandCursor: true }); + + // 按钮文本 + const buttonText = this.add.text(buttonX + 25, buttonY + 10, '返回菜单', { + fontSize: '16px', + fill: '#ffffff', + fontFamily: 'Arial' + }); + buttonText.setScrollFactor(0, 0); + buttonText.setDepth(101); + + // 按钮事件 + button.on('pointerdown', () => { + this.scene.start('BootScene'); + }); + + button.on('pointerover', () => { + button.setFillStyle(0x555555); + }); + + button.on('pointerout', () => { + button.setFillStyle(0x333333); + }); } /** diff --git a/scenes/testScenes/MiniMapTestScene.js b/scenes/testScenes/MiniMapTestScene.js index 0367f63..50681a9 100644 --- a/scenes/testScenes/MiniMapTestScene.js +++ b/scenes/testScenes/MiniMapTestScene.js @@ -5,9 +5,9 @@ import { SelectionSystem } from '../../systems/SelectionSystem.js'; import { CommandSystem } from '../../systems/CommandSystem.js'; import { MiniMap } from '../../ui/MiniMap.js'; -export default class MovementTestScene6 extends Phaser.Scene { +export default class MiniMapTestScene extends Phaser.Scene { constructor() { - super({ key: 'MovementTestScene6' }); + super({ key: 'MiniMapTestScene' }); } create() { @@ -100,6 +100,9 @@ export default class MovementTestScene6 extends Phaser.Scene { this.input.keyboard.on('keydown-SPACE', () => { this.scene.start('BootScene'); }); + + // 添加返回菜单按钮 + this.createReturnButton(); // 添加相机移动控制 this.cameraSpeed = 2; @@ -110,6 +113,40 @@ export default class MovementTestScene6 extends Phaser.Scene { right: Phaser.Input.Keyboard.KeyCodes.D }); } + + /** + * 创建返回菜单按钮 + */ + createReturnButton() { + // 创建按钮背景 + const button = this.add.rectangle(10, 130, 150, 40, 0x333333); + button.setOrigin(0, 0); + button.setScrollFactor(0, 0); + button.setDepth(10); + button.setInteractive({ useHandCursor: true }); + + // 按钮文本 + const buttonText = this.add.text(25, 140, '返回菜单', { + fontSize: '16px', + fill: '#ffffff', + fontFamily: 'Arial' + }); + buttonText.setScrollFactor(0, 0); + buttonText.setDepth(11); + + // 按钮事件 + button.on('pointerdown', () => { + this.scene.start('BootScene'); + }); + + button.on('pointerover', () => { + button.setFillStyle(0x555555); + }); + + button.on('pointerout', () => { + button.setFillStyle(0x333333); + }); + } update() { this.inputSystem.update(); diff --git a/scenes/testScenes/ResourceTestScene.js b/scenes/testScenes/ResourceTestScene.js index 3374dc7..a76f884 100644 --- a/scenes/testScenes/ResourceTestScene.js +++ b/scenes/testScenes/ResourceTestScene.js @@ -213,6 +213,21 @@ export default class ResourceTestScene extends Phaser.Scene { this.nextButtonText.setScrollFactor(0, 0); this.nextButtonText.setDepth(11); + // 返回菜单按钮 + this.returnButton = this.add.rectangle(270, 100, 120, 40, 0x333333); + this.returnButton.setOrigin(0, 0); + this.returnButton.setScrollFactor(0, 0); + this.returnButton.setDepth(10); + this.returnButton.setInteractive({ useHandCursor: true }); + + this.returnButtonText = this.add.text(280, 110, '返回菜单', { + fontSize: '16px', + fill: '#ffffff', + fontFamily: 'Arial' + }); + this.returnButtonText.setScrollFactor(0, 0); + this.returnButtonText.setDepth(11); + // 按钮事件 this.prevButton.on('pointerdown', () => { this.currentCategory = (this.currentCategory - 1 + this.resourceCategories.length) % this.resourceCategories.length; @@ -224,11 +239,17 @@ export default class ResourceTestScene extends Phaser.Scene { this.updateCategoryDisplay(); }); + this.returnButton.on('pointerdown', () => { + this.scene.start('BootScene'); + }); + // 悬停效果 this.prevButton.on('pointerover', () => this.prevButton.setFillStyle(0x555555)); this.prevButton.on('pointerout', () => this.prevButton.setFillStyle(0x333333)); this.nextButton.on('pointerover', () => this.nextButton.setFillStyle(0x555555)); this.nextButton.on('pointerout', () => this.nextButton.setFillStyle(0x333333)); + this.returnButton.on('pointerover', () => this.returnButton.setFillStyle(0x555555)); + this.returnButton.on('pointerout', () => this.returnButton.setFillStyle(0x333333)); } /** diff --git a/scenes/testScenes/SelectionAndMovementTestScene.js b/scenes/testScenes/SelectionAndMovementTestScene.js index ea43ccc..956791e 100644 --- a/scenes/testScenes/SelectionAndMovementTestScene.js +++ b/scenes/testScenes/SelectionAndMovementTestScene.js @@ -96,6 +96,43 @@ export default class SelectionAndMovementTestScene extends Phaser.Scene { this.input.keyboard.on('keydown-SPACE', () => { this.scene.start('BootScene'); }); + + // 添加返回菜单按钮 + this.createReturnButton(); + } + + /** + * 创建返回菜单按钮 + */ + createReturnButton() { + // 创建按钮背景 + const button = this.add.rectangle(10, 130, 150, 40, 0x333333); + button.setOrigin(0, 0); + button.setScrollFactor(0, 0); + button.setDepth(10); + button.setInteractive({ useHandCursor: true }); + + // 按钮文本 + const buttonText = this.add.text(25, 140, '返回菜单', { + fontSize: '16px', + fill: '#ffffff', + fontFamily: 'Arial' + }); + buttonText.setScrollFactor(0, 0); + buttonText.setDepth(11); + + // 按钮事件 + button.on('pointerdown', () => { + this.scene.start('BootScene'); + }); + + button.on('pointerover', () => { + button.setFillStyle(0x555555); + }); + + button.on('pointerout', () => { + button.setFillStyle(0x333333); + }); } update() { diff --git a/scenes/testScenes/TargetMovementTestScene.js b/scenes/testScenes/TargetMovementTestScene.js index b93cd9c..76ee7c4 100644 --- a/scenes/testScenes/TargetMovementTestScene.js +++ b/scenes/testScenes/TargetMovementTestScene.js @@ -78,6 +78,43 @@ export default class TargetMovementTestScene extends Phaser.Scene { this.input.keyboard.on('keydown-SPACE', () => { this.scene.start('BootScene'); }); + + // 添加返回菜单按钮 + this.createReturnButton(); + } + + /** + * 创建返回菜单按钮 + */ + createReturnButton() { + // 创建按钮背景 + const button = this.add.rectangle(10, 100, 150, 40, 0x333333); + button.setOrigin(0, 0); + button.setScrollFactor(0, 0); + button.setDepth(10); + button.setInteractive({ useHandCursor: true }); + + // 按钮文本 + const buttonText = this.add.text(25, 110, '返回菜单', { + fontSize: '16px', + fill: '#ffffff', + fontFamily: 'Arial' + }); + buttonText.setScrollFactor(0, 0); + buttonText.setDepth(11); + + // 按钮事件 + button.on('pointerdown', () => { + this.scene.start('BootScene'); + }); + + button.on('pointerover', () => { + button.setFillStyle(0x555555); + }); + + button.on('pointerout', () => { + button.setFillStyle(0x333333); + }); } update() { diff --git a/systems/InputSystem.js b/systems/InputSystem.js index 831b3e5..f0b2010 100644 --- a/systems/InputSystem.js +++ b/systems/InputSystem.js @@ -143,20 +143,28 @@ export class InputSystem { // 如果点中了物品,不执行后续操作,避免触发移动 this.selectionStart = null; this.dragStart = null; - } else if (this.enabledModes.selection && !this.isCameraLocked()) { - // 如果没有点中单位,且框选功能启用,且相机未锁定,开始框选操作 + } else if (this.enabledModes.selection && !this.isCameraLocked() && !this.isInPlantingMode()) { + // 如果没有点中单位,且框选功能启用,且相机未锁定,且不在种植模式,开始框选操作 // 存储框选开始时的世界坐标 this.selectionStart = { x: worldX, y: worldY }; // 没有点中单位,清除dragStart this.dragStart = null; + } else if (this.isInPlantingMode()) { + // 如果处于种植模式,不执行任何选择或框选操作 + this.selectionStart = null; + this.dragStart = null; } - } else if (pointer.rightButtonDown() && this.enabledModes.mouse) { - // 如果是右键按下且鼠标模式启用,发送移动到指定点的事件 + } else if (pointer.rightButtonDown() && this.enabledModes.mouse && !this.isInPlantingMode()) { + // 如果是右键按下且鼠标模式启用,且不在种植模式,发送移动到指定点的事件 const worldX = pointer.worldX; const worldY = pointer.worldY; this.scene.events.emit('move-to-point', worldX, worldY); // 右键点击,清除dragStart this.dragStart = null; + } else if (pointer.rightButtonDown() && this.isInPlantingMode()) { + // 如果处于种植模式,右键点击不执行任何操作 + this.dragStart = null; + this.selectionStart = null; } } @@ -219,7 +227,7 @@ export class InputSystem { const dragDistance = Math.sqrt(dx * dx + dy * dy); // 如果拖动距离超过阈值(10像素),视为拖动操作 - if (dragDistance > 10 && this.enabledModes.mouse) { + if (dragDistance > 10 && this.enabledModes.mouse && !this.isInPlantingMode()) { // 发送移动到指定点的事件,让单位移动到释放位置 this.scene.events.emit('move-to-point', currentWorldX, currentWorldY); } @@ -242,8 +250,8 @@ export class InputSystem { ); // 如果框选区域太小(宽度和高度都小于10像素),视为点击地面移动 - if (rect.width < 10 && rect.height < 10 && this.enabledModes.mouse) { - // 发送移动到指定点的事件(仅在鼠标模式启用时) + if (rect.width < 10 && rect.height < 10 && this.enabledModes.mouse && !this.isInPlantingMode()) { + // 发送移动到指定点的事件(仅在鼠标模式启用时,且不在种植模式下) this.scene.events.emit('move-to-point', pointer.worldX, pointer.worldY); } else { // 否则执行框选操作 @@ -290,6 +298,15 @@ export class InputSystem { * @returns {boolean} - 如果鼠标在UI元素上返回true,否则返回false */ isMouseOnUI(pointer) { + // 检查是否点击在作物详情面板上 + if (this.scene.cropDetailsPanel) { + const detailsRect = this.scene.cropDetailsPanel.getBounds(); + if (pointer.x >= detailsRect.x && pointer.x <= detailsRect.right && + pointer.y >= detailsRect.y && pointer.y <= detailsRect.bottom) { + return true; + } + } + return this.isMouseOnMiniMap(pointer) || this.isMouseOnJoystick(pointer) || this.isMouseOnSidebar(pointer) || @@ -297,6 +314,18 @@ export class InputSystem { this.isMouseOnItemListUI(pointer); } + /** + * 检查当前是否处于种植或收获模式 + * @returns {boolean} - 如果处于种植或收获模式返回true,否则返回false + */ + isInPlantingMode() { + // 检查场景是否处于种植模式,或者是否有取消种植按钮,或者是否显示作物详情面板 + // 这样可以确保点击取消种植按钮或收获按钮时,不会触发角色移动 + return this.scene.isPlantingMode || + (this.scene.cancelPlantingButton && this.scene.cancelPlantingButton.active) || + (this.scene.cropDetailsPanel && this.scene.cropDetailsPanel.visible); + } + /** * 检查鼠标是否在物品列表菜单上 * @param {Phaser.Input.Pointer} pointer - 指针事件对象 diff --git a/ui/InventoryUI.js b/ui/InventoryUI.js index 17e79a3..6777798 100644 --- a/ui/InventoryUI.js +++ b/ui/InventoryUI.js @@ -220,11 +220,16 @@ export class InventoryUI { */ onItemSpriteClicked(item) { console.log('onItemSpriteClicked:', item.name, 'ID:', item.id); - if (this.selectedItem && this.selectedItem.id === item.id) { - // 如果点击的是已选中的物品,取消选择 - console.log('点击已选中物品,取消选择:', item.name); + // 如果是右键点击,使用物品 + if (this.scene.input.mousePointer.rightButtonDown()) { + console.log('右键点击物品,使用物品:', item.name); + this.useItem(item); + } else if (this.selectedItem && this.selectedItem.id === item.id) { + // 如果是左键点击已选中的物品,取消选择 + console.log('左键点击已选中物品,取消选择:', item.name); this.deselectItem(); } else { + // 如果是左键点击其他物品,选中当前物品 // 如果已经有选中的物品,先取消选择 if (this.selectedItem) { console.log('已有选中物品,先取消选择:', this.selectedItem.name); @@ -236,6 +241,46 @@ export class InventoryUI { } } + /** + * 使用物品 + * @param {Object} item - 要使用的物品 + */ + useItem(item) { + console.log('useItem:', item.name, 'ID:', item.id); + + // 获取当前选中的角色(假设场景中有player属性) + const user = this.scene.player; + + if (user) { + console.log('使用物品的角色:', user.name); + + // 确保物品有场景引用 + item.scene = this.scene; + console.log('DEBUG: 设置物品场景引用:', item.scene ? '成功' : '失败'); + + // 调用物品的useFromInventory方法,从背包中使用物品 + // 注意:物品的具体使用方法(如useSeed)中会处理从背包移除的逻辑 + item.useFromInventory(user); + + // 更新UI,因为物品可能已经被移除 + this.updateUI(); + + // 对于种子类型的物品,延迟取消选择,避免背包立即关闭导致用户体验不佳 + // 这样用户可以看到种植模式的变化 + if (item.type !== 'seed') { + // 非种子类型物品,立即取消选择 + this.deselectItem(); + } else { + // 种子类型物品,延迟取消选择,给用户视觉反馈 + console.log('种子物品使用后,延迟取消选择'); + // 不立即取消选择,让用户看到种植模式的变化 + // 种植模式会在后续操作中自动取消选择 + } + } else { + console.log('没有选中的角色,无法使用物品'); + } + } + /** * 物品精灵鼠标按下事件,用于记录点击状态和位置 * @param {Object} item - 物品 @@ -243,6 +288,15 @@ export class InventoryUI { */ onItemSpriteDown(item, pointer) { console.log('onItemSpriteDown:', item.name, '记录点击位置'); + + // 右键点击直接使用物品,不处理选择和拖动 + if (pointer.rightButtonDown()) { + console.log('右键点击物品精灵,使用物品:', item.name); + this.useItem(item); + return; // 直接返回,不处理后续逻辑 + } + + // 左键点击处理选择和拖动 // 记录点击的物品和位置,用于判断是否开始拖动 this.clickItem = item; this.clickPosition = { x: pointer.x, y: pointer.y }; @@ -251,7 +305,7 @@ export class InventoryUI { // 切换选择状态:如果已选中,则取消选择;如果未选中,则选中 if (this.selectedItem && this.selectedItem.id === item.id) { // 如果点击的是已选中物品,取消选择 - console.log('点击已选中物品精灵,取消选择:', item.name); + console.log('左键点击已选中物品精灵,取消选择:', item.name); this.deselectItem(); } else { // 如果没有选中物品或点击的是另一个物品,选中当前物品 @@ -642,6 +696,11 @@ export class InventoryUI { // 显示选中物品的详情 this.showItemInfo(item); console.log('选中物品:', item.name); + + // 如果是种子类型的物品,显示使用提示 + if (item.type === 'seed') { + this.scene.events.emit('show-message', `右键点击、按Q键或点击[使用]按钮可以种植种子`); + } } /** @@ -668,7 +727,7 @@ export class InventoryUI { */ showItemInfo(item) { // 创建物品信息面板 - this.itemInfoPanel = this.scene.add.rectangle(0, 0, 200, 100, 0x000000, 0.8); + this.itemInfoPanel = this.scene.add.rectangle(0, 0, 200, 150, 0x000000, 0.8); this.itemInfoPanel.setOrigin(0, 0); this.itemInfoPanel.setStrokeStyle(1, 0xffffff); this.itemInfoPanel.setPosition( @@ -676,6 +735,9 @@ export class InventoryUI { this.container.y + this.inventory.height * this.cellSize + 20 ); + // 设置足够高的深度,确保面板显示在最上层 + this.itemInfoPanel.setDepth(150); + // 阻止事件冒泡,防止点击物品信息面板时触发角色移动 this.itemInfoPanel.setInteractive(); this.itemInfoPanel.on('pointerdown', (pointer) => { @@ -694,9 +756,231 @@ export class InventoryUI { { font: '12px Arial', fill: '#ffffff', wordWrap: { width: 180 } } ); this.itemInfoText.setScrollFactor(0); // 固定在屏幕上 + this.itemInfoText.setDepth(160); // 设置比面板更高的深度 + + // 添加"使用"按钮 + const useButton = this.scene.add.text( + this.itemInfoPanel.x + 10, + this.itemInfoPanel.y + 90, + '[使用]', + { font: '14px Arial', fill: '#00ff00' } + ); + useButton.setInteractive({ + useHandCursor: true + }); + useButton.setDepth(170); // 设置比文本更高的深度 + + // 存储当前物品引用,确保回调函数中this指向正确 + const currentItem = item; + const inventoryUI = this; + + useButton.on('pointerdown', (pointer) => { + console.log('点击使用按钮,使用物品:', currentItem.name); + inventoryUI.useItem(currentItem); + return false; // 阻止事件冒泡 + }); + useButton.on('pointerover', (pointer) => { + useButton.setFill('#ffff00'); + return false; // 阻止事件冒泡 + }); + useButton.on('pointerout', (pointer) => { + useButton.setFill('#00ff00'); + return false; // 阻止事件冒泡 + }); + useButton.setScrollFactor(0); // 固定在屏幕上 + + // 如果是种子类型的物品,添加"种植/取消种植"按钮 + // 如果是作物类型的物品,添加"制作种子"按钮 + let actionButton = null; + let buttonX = this.itemInfoPanel.x + 80; + let buttonY = this.itemInfoPanel.y + 90; + + if (item.type === 'seed') { + // 检查当前是否处于种植模式 + const isPlantingMode = this.scene.isPlantingMode || false; + const buttonText = isPlantingMode ? '[取消种植]' : '[种植]'; + const buttonColor = isPlantingMode ? '#ff0000' : '#00ff00'; + + actionButton = this.scene.add.text( + buttonX, + buttonY, + buttonText, + { font: '14px Arial', fill: buttonColor } + ); + // 设置足够高的深度,确保按钮可以点击 + actionButton.setDepth(200); + actionButton.setScrollFactor(0); // 固定在屏幕上 + actionButton.setInteractive({ + useHandCursor: true, + draggable: false, + cursor: 'pointer' + }); + + // 确保事件监听正确绑定 + actionButton.removeAllListeners(); + + actionButton.on('pointerdown', (pointer) => { + console.log('DEBUG: 种植/取消种植按钮点击事件触发'); + if (isPlantingMode) { + // 如果是种植模式,调用取消种植 + console.log('点击取消种植按钮,取消种植:', currentItem.name); + this.scene.cancelPlantingMode(); + } else { + // 否则,使用种子开始种植 + console.log('点击种植按钮,使用种子:', currentItem.name); + inventoryUI.useItem(currentItem); + } + return false; // 阻止事件冒泡 + }); + actionButton.on('pointerover', (pointer) => { + actionButton.setFill('#ffff00'); + return false; // 阻止事件冒泡 + }); + actionButton.on('pointerout', (pointer) => { + actionButton.setFill(buttonColor); + return false; // 阻止事件冒泡 + }); + + console.log('DEBUG: 种植/取消种植按钮创建完成,深度:', actionButton.depth); + } else if (item.type === 'food' && ['wheat', 'carrot'].includes(item.itemTypeId)) { + // 如果是作物类型的物品,添加"制作种子"按钮 + const buttonText = '[制作种子]'; + const buttonColor = '#0080ff'; + + actionButton = this.scene.add.text( + buttonX, + buttonY, + buttonText, + { font: '14px Arial', fill: buttonColor } + ); + // 设置足够高的深度,确保按钮可以点击 + actionButton.setDepth(200); + actionButton.setScrollFactor(0); // 固定在屏幕上 + actionButton.setInteractive({ + useHandCursor: true, + draggable: false, + cursor: 'pointer' + }); + + // 确保事件监听正确绑定 + actionButton.removeAllListeners(); + + actionButton.on('pointerdown', (pointer) => { + console.log('DEBUG: 制作种子按钮点击事件触发'); + inventoryUI.craftSeeds(currentItem); + return false; // 阻止事件冒泡 + }); + actionButton.on('pointerover', (pointer) => { + actionButton.setFill('#ffff00'); + return false; // 阻止事件冒泡 + }); + actionButton.on('pointerout', (pointer) => { + actionButton.setFill(buttonColor); + return false; // 阻止事件冒泡 + }); + + console.log('DEBUG: 制作种子按钮创建完成,深度:', actionButton.depth); + } + + // 存储按钮引用,以便后续销毁 + this.itemInfoButton = useButton; + this.plantButton = actionButton; this.container.add(this.itemInfoPanel); this.container.add(this.itemInfoText); + this.container.add(useButton); + + // 如果有额外按钮(种植/制作种子),添加到容器中 + if (actionButton) { + this.container.add(actionButton); + } + + // 添加拾取按钮 + const dropButton = this.scene.add.text( + this.itemInfoPanel.x + 10, + this.itemInfoPanel.y + 115, + '[丢弃]', + { font: '14px Arial', fill: '#ff0000' } + ); + dropButton.setInteractive({ + useHandCursor: true + }); + dropButton.setDepth(170); // 设置比文本更高的深度 + + dropButton.on('pointerdown', (pointer) => { + console.log('点击丢弃按钮,丢弃物品:', currentItem.name); + inventoryUI.dropItem(currentItem); + return false; // 阻止事件冒泡 + }); + dropButton.on('pointerover', (pointer) => { + dropButton.setFill('#ffff00'); + return false; // 阻止事件冒泡 + }); + dropButton.on('pointerout', (pointer) => { + dropButton.setFill('#ff0000'); + return false; // 阻止事件冒泡 + }); + dropButton.setScrollFactor(0); // 固定在屏幕上 + this.container.add(dropButton); + + // 存储拾取按钮引用,以便后续销毁 + this.dropButton = dropButton; + } + + /** + * 更新种植按钮状态 + * @param {boolean} isPlanting - 是否处于种植模式 + */ + updatePlantButtonState(isPlanting) { + // 如果有显示的物品信息且是种子类型,更新按钮状态 + if (this.itemInfoPanel && this.plantButton) { + console.log('DEBUG: updatePlantButtonState 方法被调用,isPlanting:', isPlanting); + // 设置足够高的深度,确保按钮可以点击 + this.plantButton.setDepth(200); + // 确保按钮可见 + this.plantButton.setVisible(true); + // 更新按钮文本和颜色 + this.plantButton.setText(isPlanting ? '[取消种植]' : '[种植]'); + this.plantButton.setFill(isPlanting ? '#ff0000' : '#00ff00'); + + // 重新绑定点击事件 + const currentItem = this.selectedItem; + const inventoryUI = this; + + // 移除旧的事件监听器 + this.plantButton.removeAllListeners(); + + // 确保按钮可以交互 + this.plantButton.setInteractive({ + useHandCursor: true, + draggable: false, + cursor: 'pointer' + }); + + // 重新添加事件监听器 + this.plantButton.on('pointerdown', (pointer) => { + console.log('DEBUG: 更新后的种植/取消种植按钮点击事件触发'); + if (isPlanting) { + // 如果是种植模式,调用取消种植 + console.log('点击取消种植按钮,取消种植:', currentItem.name); + inventoryUI.scene.cancelPlantingMode(); + } else { + // 否则,使用种子开始种植 + console.log('点击种植按钮,使用种子:', currentItem.name); + inventoryUI.useItem(currentItem); + } + return false; // 阻止事件冒泡 + }); + this.plantButton.on('pointerover', (pointer) => { + this.plantButton.setFill('#ffff00'); + return false; // 阻止事件冒泡 + }); + this.plantButton.on('pointerout', (pointer) => { + this.plantButton.setFill(isPlanting ? '#ff0000' : '#00ff00'); + return false; // 阻止事件冒泡 + }); + console.log('DEBUG: 种植/取消种植按钮状态更新完成'); + } } /** @@ -706,11 +990,57 @@ export class InventoryUI { if (this.itemInfoPanel) { this.itemInfoPanel.destroy(); this.itemInfoText.destroy(); + if (this.itemInfoButton) { + this.itemInfoButton.destroy(); + this.itemInfoButton = null; + } + if (this.plantButton) { + this.plantButton.destroy(); + this.plantButton = null; + } + if (this.dropButton) { + this.dropButton.destroy(); + this.dropButton = null; + } this.itemInfoPanel = null; this.itemInfoText = null; } } + /** + * 丢弃物品 + * @param {Object} item - 要丢弃的物品 + */ + dropItem(item) { + console.log('dropItem:', item.name, 'ID:', item.id); + + // 从背包中移除物品 + const removedItem = this.inventory.removeItem(item.id); + if (!removedItem) { + console.log('无法从背包中移除物品:', item.name); + return; + } + + // 获取物品ID和基本信息 + const itemId = removedItem.itemTypeId || removedItem.id; + + // 在角色位置创建该物品 + if (this.scene.itemManager) { + const player = this.scene.player; + this.scene.itemManager.createItem(itemId, player.x, player.y); + console.log('已在角色位置创建丢弃的物品:', removedItem.name); + } + + // 更新UI显示 + this.updateUI(); + + // 显示丢弃成功消息 + this.scene.events.emit('show-message', `已丢弃 ${removedItem.name}`); + + // 取消选择物品 + this.deselectItem(); + } + /** * 更新UI显示 */ @@ -847,6 +1177,84 @@ export class InventoryUI { return item; } + /** + * 制作种子 + * @param {Object} item - 要制作种子的作物 + */ + craftSeeds(item) { + console.log('craftSeeds:', item.name, 'ID:', item.id); + + // 检查物品是否可以制作种子 + if (item.type !== 'food' || !['wheat', 'carrot'].includes(item.itemTypeId)) { + console.log('该物品不能制作种子:', item.name); + return; + } + + // 从背包中移除作物 + const removedItem = this.inventory.removeItem(item.id); + if (!removedItem) { + console.log('无法从背包中移除作物:', item.name); + return; + } + + // 制作种子数量(1个作物制作2个种子) + const seedsCount = 2; + + // 获取对应作物的种子ID + const seedId = `${item.itemTypeId}_seed`; + + // 使用ItemManager创建种子物品 + if (this.scene.itemManager) { + let successfullyAdded = 0; + let seedsToDrop = []; + + // 先创建所有种子 + for (let i = 0; i < seedsCount; i++) { + // 创建种子物品 + const seedItem = this.scene.itemManager.createItem(seedId, 0, 0); + if (seedItem) { + // 尝试将种子添加到背包 + const success = this.inventory.addItem(seedItem); + if (success) { + successfullyAdded++; + } else { + // 如果背包空间不足,将种子添加到待丢弃列表 + seedsToDrop.push(seedItem); + } + } + } + + // 如果背包空间不足,将无法放入背包的种子放到地图上 + if (seedsToDrop.length > 0 && this.scene.player) { + const player = this.scene.player; + seedsToDrop.forEach(seedItem => { + // 设置种子位置为玩家位置 + seedItem.x = player.x; + seedItem.y = player.y; + // 确保种子被正确添加到场景中 + this.scene.add.existing(seedItem); + console.log('背包空间不足,已将种子放到地图上:', seedItem.name); + }); + } + + // 更新UI显示 + this.updateUI(); + + // 显示制作成功消息 + let message = `成功制作了${successfullyAdded}个${seedId.replace('_seed', '')}种子`; + if (seedsToDrop.length > 0) { + message += `,${seedsToDrop.length}个种子因背包空间不足已放到地上`; + } + this.scene.events.emit('show-message', message); + + console.log(`成功制作了${successfullyAdded}个${seedId.replace('_seed', '')}种子,${seedsToDrop.length}个种子放到了地上`); + } else { + console.log('场景中没有ItemManager,无法制作种子'); + // 如果无法制作种子,将作物归还 + this.inventory.addItem(item); + } + } + /** * 销毁背包UI */