// 物品类:表示游戏中的单个物品实体 export default class Item extends Phaser.GameObjects.Sprite { constructor(scene, x, y, itemData) { // 从itemData中提取精灵属性 const { id, name, description, type, weight, volume, value, gridSize, sprite, properties } = itemData; // 创建一个简单的图形纹理作为物品精灵 if (!scene.textures.exists(id)) { const canvas = document.createElement('canvas'); canvas.width = sprite.width; canvas.height = sprite.height; const ctx = canvas.getContext('2d'); // 设置物品颜色 ctx.fillStyle = `#${sprite.color.toString(16).padStart(6, '0')}`; ctx.fillRect(0, 0, sprite.width, sprite.height); // 添加物品边框 ctx.strokeStyle = '#000000'; ctx.lineWidth = 1; ctx.strokeRect(0, 0, sprite.width, sprite.height); // 添加物品ID的第一个字符作为图标 ctx.fillStyle = '#ffffff'; ctx.font = `${sprite.width * 0.8}px Arial`; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(id.charAt(0).toUpperCase(), sprite.width / 2, sprite.height / 2); // 将canvas添加为纹理 scene.textures.addCanvas(id, canvas); } // 调用父类构造函数创建精灵 super(scene, x, y, id); // 设置物品属性 this.itemTypeId = id; // 物品类型ID,用于识别物品类型 this.id = `${id}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; // 生成唯一ID this.name = name; this.description = description; this.type = type; this.weight = weight; this.volume = volume; this.value = value; this.gridSize = gridSize || { width: 1, height: 1 }; // 默认1x1网格 this.properties = properties; // 背包相关属性 this.position = null; // 在背包中的位置 this.positionInInventory = null; // 在背包中的位置(保持向后兼容) this.inInventory = false; // 添加到场景中 scene.add.existing(this); scene.physics.add.existing(this, true); // 静态物体,不响应物理碰撞 // 设置物品的碰撞体 this.setSize(sprite.width, sprite.height); // 设置物品的交互性 this.setInteractive({ useHandCursor: true }); // 绑定点击事件 this.on('pointerdown', (pointer) => { // 检查鼠标是否在UI元素上,如果是则不处理 if (this.scene.inputSystem && this.scene.inputSystem.isMouseOnUI && this.scene.inputSystem.isMouseOnUI(pointer)) { return; } // 添加视觉反馈:缩放物品 this.scene.tweens.add({ targets: this, scale: { from: 1, to: 1.2, duration: 100, yoyo: true, repeat: 1 } }); this.onItemClicked(); }); } /** * 检查单位是否在交互距离内 * @param {Object} unit - 要检查的单位 * @returns {boolean} - 是否在交互距离内 */ isInInteractionRange(unit) { const maxDistance = 50; // 最大交互距离 const dx = this.x - unit.x; const dy = this.y - unit.y; const distance = Math.sqrt(dx * dx + dy * dy); return distance <= maxDistance; } /** * 物品被点击时的处理函数 */ onItemClicked() { // 触发物品点击事件 this.scene.events.emit('item-clicked', this); } /** * 拾取物品 * @param {Object} user - 拾取物品的单位 */ pickup(user) { // 检查是否在交互范围内 if (!this.isInInteractionRange(user)) { console.log('距离太远,无法拾取物品'); return; } console.log(`${user.name} 拾取了 ${this.name}`); // 检查用户是否有背包 if (user.inventory) { // 尝试将物品添加到背包 const success = user.inventory.addItem(this); if (success) { this.inInventory = true; // 保存场景引用,避免在destroy后访问undefined const scene = this.scene; // 如果场景中有背包UI,更新UI if (scene && scene.inventoryUI) { scene.inventoryUI.updateUI(); } // 发射物品拾取事件 if (scene && scene.events) { scene.events.emit('item-picked-up', this, user); } // 成功拾取后从地图上删除物品,避免潜在bug this.destroy(); } else { console.log('背包空间不足'); } } else { // 如果没有背包系统,简单移除物品 this.destroy(); } } /** * 从背包中使用物品 * @param {Object} user - 使用物品的单位 */ useFromInventory(user) { // 使用物品 this.use(user); // 从背包中移除物品 if (user.inventory) { user.inventory.removeItem(this.id); } } /** * 创建物品实例(静态方法) * @param {Object} itemData - 物品数据 * @returns {Item} 物品实例 */ static createFromData(itemData) { // 这个方法需要在具体场景中实现 // 因为需要场景上下文来创建精灵 return null; } /** * 使用物品 * @param {Object} user - 使用物品的单位 */ use(user) { // 根据物品类型和属性执行不同的使用逻辑 switch (this.type) { case 'food': this.useFood(user); break; case 'medical': this.useMedical(user); break; case 'tool': this.useTool(user); break; case 'weapon': this.equipWeapon(user); break; case 'seed': this.useSeed(user); break; default: console.log(`无法使用物品:${this.name}`); } } /** * 使用种子物品 * @param {Object} user - 使用物品的单位 */ useSeed(user) { console.log('DEBUG: useSeed 方法被调用'); if (this.properties.plantable) { console.log(`DEBUG: ${user.name} 准备种植 ${this.name}`); // 触发种植事件,让场景处理具体的种植逻辑 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: 种子不可种植'); } } /** * 使用食物物品 * @param {Object} user - 使用物品的单位 */ useFood(user) { if (this.properties.drinkable) { // 处理饮水逻辑 console.log(`${user.name} 喝了 ${this.name}`); if (user.hydration !== undefined) { user.hydration = Math.min(100, user.hydration + this.properties.hydration); } } else if (this.properties.edible) { // 处理进食逻辑 console.log(`${user.name} 吃了 ${this.name}`); if (user.nutrition !== undefined) { user.nutrition = Math.min(100, user.nutrition + this.properties.nutrition); } if (user.hydration !== undefined) { user.hydration = Math.min(100, user.hydration + (this.properties.hydration || 0)); } } // 使用后移除物品 this.destroy(); } /** * 使用医疗物品 * @param {Object} user - 使用物品的单位 */ useMedical(user) { if (this.properties.heal_amount && user.health !== undefined) { console.log(`${user.name} 使用了 ${this.name}`); user.health = Math.min(100, user.health + this.properties.heal_amount); // 使用后移除物品 this.destroy(); } } /** * 使用工具物品 * @param {Object} user - 使用物品的单位 */ useTool(user) { console.log(`${user.name} 使用了工具:${this.name}`); // 工具使用逻辑可以根据具体工具类型扩展 } /** * 装备武器 * @param {Object} user - 装备武器的单位 */ equipWeapon(user) { console.log(`${user.name} 装备了武器:${this.name}`); // 装备武器逻辑 if (user.equipWeapon) { user.equipWeapon(this); } // 装备后可以选择保留物品或移除,这里选择保留 } /** * 获取物品的详细信息 * @returns {Object} 物品信息对象 */ getInfo() { return { id: this.id, name: this.name, description: this.description, type: this.type, weight: this.weight, volume: this.volume, value: this.value, gridSize: this.gridSize, properties: this.properties }; } }