mirror of
http://junepve.top:3000/chicrobot/CINC.git
synced 2026-10-30 06:41:29 +08:00
feat(item) 添加物品系统
This commit is contained in:
1 parent
606e833f33
commit
2f7210f47e
4 files changed
+1127
No files matched your search
+114
@@ -0,0 +1,114 @@
|
|||||||
|
{
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "water_bottle",
|
||||||
|
"name": "瓶装水",
|
||||||
|
"description": "一瓶干净的饮用水,可以解渴。",
|
||||||
|
"type": "food",
|
||||||
|
"weight": 1.0,
|
||||||
|
"volume": 1.0,
|
||||||
|
"value": 5,
|
||||||
|
"sprite": {
|
||||||
|
"width": 16,
|
||||||
|
"height": 16,
|
||||||
|
"color": 255
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"drinkable": true,
|
||||||
|
"nutrition": 0,
|
||||||
|
"hydration": 50
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "canned_food",
|
||||||
|
"name": "罐头食品",
|
||||||
|
"description": "一罐保质期很长的食品,可以提供营养。",
|
||||||
|
"type": "food",
|
||||||
|
"weight": 1.5,
|
||||||
|
"volume": 1.0,
|
||||||
|
"value": 10,
|
||||||
|
"sprite": {
|
||||||
|
"width": 16,
|
||||||
|
"height": 16,
|
||||||
|
"color": 16711680
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"edible": true,
|
||||||
|
"nutrition": 100,
|
||||||
|
"hydration": 20
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "crowbar",
|
||||||
|
"name": "撬棍",
|
||||||
|
"description": "多功能工具,可以撬开门锁或作为武器。",
|
||||||
|
"type": "tool",
|
||||||
|
"weight": 3.0,
|
||||||
|
"volume": 2.0,
|
||||||
|
"value": 20,
|
||||||
|
"sprite": {
|
||||||
|
"width": 16,
|
||||||
|
"height": 16,
|
||||||
|
"color": 8421504
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"tool_quality": 2,
|
||||||
|
"weapon_damage": 15
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "first_aid_kit",
|
||||||
|
"name": "急救包",
|
||||||
|
"description": "包含基本医疗用品,可以治疗伤口。",
|
||||||
|
"type": "medical",
|
||||||
|
"weight": 1.0,
|
||||||
|
"volume": 1.5,
|
||||||
|
"value": 30,
|
||||||
|
"sprite": {
|
||||||
|
"width": 16,
|
||||||
|
"height": 16,
|
||||||
|
"color": 16777215
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"heal_amount": 50,
|
||||||
|
"usable": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "flashlight",
|
||||||
|
"name": "手电筒",
|
||||||
|
"description": "可以在黑暗中提供照明。",
|
||||||
|
"type": "tool",
|
||||||
|
"weight": 0.5,
|
||||||
|
"volume": 0.5,
|
||||||
|
"value": 15,
|
||||||
|
"sprite": {
|
||||||
|
"width": 16,
|
||||||
|
"height": 16,
|
||||||
|
"color": 16776960
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"light_range": 10,
|
||||||
|
"battery_life": 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "knife",
|
||||||
|
"name": "小刀",
|
||||||
|
"description": "一把锋利的小刀,可以用作工具或武器。",
|
||||||
|
"type": "weapon",
|
||||||
|
"weight": 0.8,
|
||||||
|
"volume": 1.0,
|
||||||
|
"value": 12,
|
||||||
|
"sprite": {
|
||||||
|
"width": 16,
|
||||||
|
"height": 16,
|
||||||
|
"color": 4194304
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"weapon_damage": 10,
|
||||||
|
"tool_quality": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
+204
@@ -0,0 +1,204 @@
|
|||||||
|
// 物品类:表示游戏中的单个物品实体
|
||||||
|
|
||||||
|
export default class Item extends Phaser.GameObjects.Sprite {
|
||||||
|
constructor(scene, x, y, itemData) {
|
||||||
|
// 从itemData中提取精灵属性
|
||||||
|
const { id, name, description, type, weight, volume, value, 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.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.description = description;
|
||||||
|
this.type = type;
|
||||||
|
this.weight = weight;
|
||||||
|
this.volume = volume;
|
||||||
|
this.value = value;
|
||||||
|
this.properties = properties;
|
||||||
|
|
||||||
|
// 添加到场景中
|
||||||
|
scene.add.existing(this);
|
||||||
|
scene.physics.add.existing(this, true); // 静态物体,不响应物理碰撞
|
||||||
|
|
||||||
|
// 设置物品的碰撞体
|
||||||
|
this.setSize(sprite.width, sprite.height);
|
||||||
|
|
||||||
|
// 设置物品的交互性
|
||||||
|
this.setInteractive({
|
||||||
|
useHandCursor: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// 绑定点击事件
|
||||||
|
this.on('pointerdown', () => {
|
||||||
|
// 添加视觉反馈:缩放物品
|
||||||
|
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) {
|
||||||
|
console.log(`${user.name} 拾取了 ${this.name}`);
|
||||||
|
// 这里可以添加物品到背包的逻辑
|
||||||
|
// 暂时简单移除物品
|
||||||
|
this.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用物品
|
||||||
|
* @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;
|
||||||
|
default:
|
||||||
|
console.log(`无法使用物品:${this.name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用食物物品
|
||||||
|
* @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,
|
||||||
|
properties: this.properties
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,315 @@
|
|||||||
|
// 物品管理器:负责加载、管理和创建物品
|
||||||
|
|
||||||
|
export class ItemManager {
|
||||||
|
constructor(scene) {
|
||||||
|
this.scene = scene;
|
||||||
|
this.itemTemplates = new Map(); // 存储物品模板
|
||||||
|
this.activeItems = new Set(); // 存储当前场景中的物品实例
|
||||||
|
this.isDataLoaded = false; // 标记物品数据是否已加载
|
||||||
|
this.loadCallbacks = []; // 存储数据加载完成后的回调函数
|
||||||
|
|
||||||
|
// 加载物品数据
|
||||||
|
this.loadItemData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注册数据加载完成回调
|
||||||
|
* @param {Function} callback - 回调函数
|
||||||
|
*/
|
||||||
|
onDataLoaded(callback) {
|
||||||
|
if (this.isDataLoaded) {
|
||||||
|
callback();
|
||||||
|
} else {
|
||||||
|
this.loadCallbacks.push(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载物品数据
|
||||||
|
*/
|
||||||
|
async loadItemData() {
|
||||||
|
try {
|
||||||
|
// 从JSON文件加载物品数据
|
||||||
|
const response = await fetch('./data/items.json');
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
// 存储物品模板
|
||||||
|
data.items.forEach(itemData => {
|
||||||
|
this.itemTemplates.set(itemData.id, itemData);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`成功加载 ${this.itemTemplates.size} 种物品模板`);
|
||||||
|
|
||||||
|
// 设置数据已加载标记
|
||||||
|
this.isDataLoaded = true;
|
||||||
|
|
||||||
|
// 调用所有数据加载完成回调
|
||||||
|
this.loadCallbacks.forEach(callback => callback());
|
||||||
|
this.loadCallbacks = [];
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载物品数据失败:', error);
|
||||||
|
// 加载失败时,使用默认物品数据
|
||||||
|
this.loadDefaultItemData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载默认物品数据(当JSON文件加载失败时使用)
|
||||||
|
*/
|
||||||
|
loadDefaultItemData() {
|
||||||
|
const defaultItems = [
|
||||||
|
{
|
||||||
|
id: "water_bottle",
|
||||||
|
name: "瓶装水",
|
||||||
|
description: "一瓶干净的饮用水,可以解渴。",
|
||||||
|
type: "food",
|
||||||
|
weight: 1.0,
|
||||||
|
volume: 1.0,
|
||||||
|
value: 5,
|
||||||
|
sprite: {
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
color: 0x0000ff
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
drinkable: true,
|
||||||
|
nutrition: 0,
|
||||||
|
hydration: 50
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "canned_food",
|
||||||
|
name: "罐头食品",
|
||||||
|
description: "一罐保质期很长的食品,可以提供营养。",
|
||||||
|
type: "food",
|
||||||
|
weight: 1.5,
|
||||||
|
volume: 1.0,
|
||||||
|
value: 10,
|
||||||
|
sprite: {
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
color: 0xff0000
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
edible: true,
|
||||||
|
nutrition: 100,
|
||||||
|
hydration: 20
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "crowbar",
|
||||||
|
name: "撬棍",
|
||||||
|
description: "多功能工具,可以撬开门锁或作为武器。",
|
||||||
|
type: "tool",
|
||||||
|
weight: 3.0,
|
||||||
|
volume: 2.0,
|
||||||
|
value: 20,
|
||||||
|
sprite: {
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
color: 0x808080
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
tool_quality: 2,
|
||||||
|
weapon_damage: 15
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "first_aid_kit",
|
||||||
|
name: "急救包",
|
||||||
|
description: "包含基本医疗用品,可以治疗伤口。",
|
||||||
|
type: "medical",
|
||||||
|
weight: 1.0,
|
||||||
|
volume: 1.5,
|
||||||
|
value: 30,
|
||||||
|
sprite: {
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
color: 0xffffff
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
heal_amount: 50,
|
||||||
|
usable: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "flashlight",
|
||||||
|
name: "手电筒",
|
||||||
|
description: "可以在黑暗中提供照明。",
|
||||||
|
type: "tool",
|
||||||
|
weight: 0.5,
|
||||||
|
volume: 0.5,
|
||||||
|
value: 15,
|
||||||
|
sprite: {
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
color: 0xffff00
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
light_range: 10,
|
||||||
|
battery_life: 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "knife",
|
||||||
|
name: "小刀",
|
||||||
|
description: "一把锋利的小刀,可以用作工具或武器。",
|
||||||
|
type: "weapon",
|
||||||
|
weight: 0.8,
|
||||||
|
volume: 1.0,
|
||||||
|
value: 12,
|
||||||
|
sprite: {
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
color: 0x404040
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
weapon_damage: 10,
|
||||||
|
tool_quality: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
defaultItems.forEach(itemData => {
|
||||||
|
this.itemTemplates.set(itemData.id, itemData);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`使用默认物品数据,加载了 ${this.itemTemplates.size} 种物品模板`);
|
||||||
|
|
||||||
|
// 设置数据已加载标记
|
||||||
|
this.isDataLoaded = true;
|
||||||
|
|
||||||
|
// 调用所有数据加载完成回调
|
||||||
|
this.loadCallbacks.forEach(callback => callback());
|
||||||
|
this.loadCallbacks = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据物品ID创建物品实例
|
||||||
|
* @param {string} itemId - 物品ID
|
||||||
|
* @param {number} x - 物品位置X坐标
|
||||||
|
* @param {number} y - 物品位置Y坐标
|
||||||
|
* @returns {Item|null} - 创建的物品实例,或null如果物品ID不存在
|
||||||
|
*/
|
||||||
|
createItem(itemId, x, y) {
|
||||||
|
const itemData = this.itemTemplates.get(itemId);
|
||||||
|
if (!itemData) {
|
||||||
|
console.error(`未知物品ID: ${itemId}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 动态导入Item类
|
||||||
|
import('./Item.js').then(({ default: Item }) => {
|
||||||
|
const item = new Item(this.scene, x, y, itemData);
|
||||||
|
|
||||||
|
// 将物品添加到活动物品集合中
|
||||||
|
this.activeItems.add(item);
|
||||||
|
|
||||||
|
// 监听物品销毁事件,从集合中移除
|
||||||
|
item.on('destroy', () => {
|
||||||
|
this.activeItems.delete(item);
|
||||||
|
});
|
||||||
|
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在随机位置创建随机物品
|
||||||
|
* @returns {Item|null} - 创建的物品实例,或null如果没有物品模板
|
||||||
|
*/
|
||||||
|
createRandomItem() {
|
||||||
|
if (this.itemTemplates.size === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 随机选择一个物品模板
|
||||||
|
const itemIds = Array.from(this.itemTemplates.keys());
|
||||||
|
const randomItemId = itemIds[Math.floor(Math.random() * itemIds.length)];
|
||||||
|
|
||||||
|
// 随机选择一个位置
|
||||||
|
const worldBounds = this.scene.physics.world.bounds;
|
||||||
|
const x = Phaser.Math.Between(worldBounds.x, worldBounds.right);
|
||||||
|
const y = Phaser.Math.Between(worldBounds.y, worldBounds.bottom);
|
||||||
|
|
||||||
|
// 创建物品
|
||||||
|
return this.createItem(randomItemId, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据物品类型创建物品
|
||||||
|
* @param {string} type - 物品类型
|
||||||
|
* @param {number} x - 物品位置X坐标
|
||||||
|
* @param {number} y - 物品位置Y坐标
|
||||||
|
* @returns {Item|null} - 创建的物品实例,或null如果没有对应类型的物品
|
||||||
|
*/
|
||||||
|
createItemByType(type, x, y) {
|
||||||
|
// 筛选出指定类型的物品
|
||||||
|
const typeItems = Array.from(this.itemTemplates.values()).filter(item => item.type === type);
|
||||||
|
if (typeItems.length === 0) {
|
||||||
|
console.error(`没有找到类型为 ${type} 的物品`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 随机选择一个该类型的物品
|
||||||
|
const randomItemData = typeItems[Math.floor(Math.random() * typeItems.length)];
|
||||||
|
|
||||||
|
// 动态导入Item类
|
||||||
|
import('./Item.js').then(({ default: Item }) => {
|
||||||
|
const item = new Item(this.scene, x, y, randomItemData);
|
||||||
|
|
||||||
|
// 将物品添加到活动物品集合中
|
||||||
|
this.activeItems.add(item);
|
||||||
|
|
||||||
|
// 监听物品销毁事件,从集合中移除
|
||||||
|
item.on('destroy', () => {
|
||||||
|
this.activeItems.delete(item);
|
||||||
|
});
|
||||||
|
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取物品模板
|
||||||
|
* @param {string} itemId - 物品ID
|
||||||
|
* @returns {Object|null} - 物品模板数据,或null如果物品ID不存在
|
||||||
|
*/
|
||||||
|
getItemTemplate(itemId) {
|
||||||
|
return this.itemTemplates.get(itemId) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有物品模板
|
||||||
|
* @returns {Map} - 所有物品模板的Map对象
|
||||||
|
*/
|
||||||
|
getAllItemTemplates() {
|
||||||
|
return this.itemTemplates;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前场景中的所有物品实例
|
||||||
|
* @returns {Set} - 当前场景中的所有物品实例的Set对象
|
||||||
|
*/
|
||||||
|
getActiveItems() {
|
||||||
|
return this.activeItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理所有物品实例
|
||||||
|
*/
|
||||||
|
clearAllItems() {
|
||||||
|
this.activeItems.forEach(item => {
|
||||||
|
item.destroy();
|
||||||
|
});
|
||||||
|
this.activeItems.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 销毁物品管理器
|
||||||
|
*/
|
||||||
|
destroy() {
|
||||||
|
this.clearAllItems();
|
||||||
|
this.itemTemplates.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,494 @@
|
|||||||
|
// 物品系统测试场景
|
||||||
|
|
||||||
|
import Unit from '../objects/Unit.js';
|
||||||
|
import { InputSystem } from '../systems/InputSystem.js';
|
||||||
|
import { SelectionSystem } from '../systems/SelectionSystem.js';
|
||||||
|
import { CommandSystem } from '../systems/CommandSystem.js';
|
||||||
|
import { ItemManager } from '../items/ItemManager.js';
|
||||||
|
|
||||||
|
export default class ItemTestScene extends Phaser.Scene {
|
||||||
|
constructor() {
|
||||||
|
super({ key: 'ItemTestScene' });
|
||||||
|
}
|
||||||
|
|
||||||
|
create() {
|
||||||
|
// 物理世界和相机边界
|
||||||
|
const worldSize = 1000;
|
||||||
|
this.physics.world.setBounds(-worldSize, -worldSize, worldSize * 2, worldSize * 2);
|
||||||
|
this.cameras.main.setBounds(-worldSize, -worldSize, worldSize * 2, worldSize * 2);
|
||||||
|
this.cameras.main.centerOn(0, 0);
|
||||||
|
|
||||||
|
// 初始化系统
|
||||||
|
this.inputSystem = new InputSystem(this, {
|
||||||
|
keyboard: true,
|
||||||
|
mouse: true,
|
||||||
|
joystick: false,
|
||||||
|
selection: true
|
||||||
|
});
|
||||||
|
this.selectionSystem = new SelectionSystem(this);
|
||||||
|
this.commandSystem = new CommandSystem(this);
|
||||||
|
|
||||||
|
// 创建单位组
|
||||||
|
this.unitGroup = this.add.group();
|
||||||
|
|
||||||
|
// 创建一个测试单位
|
||||||
|
const unit = new Unit(this, 0, 0, 'player');
|
||||||
|
// 为单位添加一些属性,用于测试物品效果
|
||||||
|
unit.name = '测试单位';
|
||||||
|
unit.health = 100;
|
||||||
|
unit.nutrition = 50;
|
||||||
|
unit.hydration = 50;
|
||||||
|
unit.equipWeapon = function(weapon) {
|
||||||
|
this.weapon = weapon;
|
||||||
|
console.log(`${this.name} 装备了 ${weapon.name}`);
|
||||||
|
};
|
||||||
|
this.unitGroup.add(unit);
|
||||||
|
|
||||||
|
// 自动选中单位
|
||||||
|
this.events.emit('select-unit', unit);
|
||||||
|
|
||||||
|
// 添加碰撞检测
|
||||||
|
this.physics.add.collider(this.unitGroup, this.unitGroup);
|
||||||
|
|
||||||
|
// 初始化物品管理器
|
||||||
|
this.itemManager = new ItemManager(this);
|
||||||
|
|
||||||
|
// 当物品数据加载完成后创建初始物品
|
||||||
|
this.itemManager.onDataLoaded(() => {
|
||||||
|
this.createInitialItems();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 创建侧边栏UI(先创建,确保它在最底层)
|
||||||
|
this.createSidebar();
|
||||||
|
|
||||||
|
// 添加场景说明文本
|
||||||
|
const titleText = this.add.text(10, 10, '物品系统测试场景', {
|
||||||
|
fontSize: '20px',
|
||||||
|
fill: '#ffffff'
|
||||||
|
});
|
||||||
|
titleText.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
titleText.setDepth(10); // 设置深度,确保显示在侧边栏上方
|
||||||
|
|
||||||
|
const moveText = this.add.text(10, 40, 'WASD或方向键移动单位,左键点击选择单位', {
|
||||||
|
fontSize: '16px',
|
||||||
|
fill: '#ffffff'
|
||||||
|
});
|
||||||
|
moveText.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
moveText.setDepth(10); // 设置深度,确保显示在侧边栏上方
|
||||||
|
|
||||||
|
const itemText = this.add.text(10, 70, '点击物品查看信息,右键移动到物品位置', {
|
||||||
|
fontSize: '16px',
|
||||||
|
fill: '#ffffff'
|
||||||
|
});
|
||||||
|
itemText.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
itemText.setDepth(10); // 设置深度,确保显示在侧边栏上方
|
||||||
|
|
||||||
|
const key1Text = this.add.text(10, 100, '按1键:创建随机物品', {
|
||||||
|
fontSize: '16px',
|
||||||
|
fill: '#ffffff'
|
||||||
|
});
|
||||||
|
key1Text.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
key1Text.setDepth(10); // 设置深度,确保显示在侧边栏上方
|
||||||
|
|
||||||
|
const key2Text = this.add.text(10, 130, '按2键:创建食物类物品', {
|
||||||
|
fontSize: '16px',
|
||||||
|
fill: '#ffffff'
|
||||||
|
});
|
||||||
|
key2Text.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
key2Text.setDepth(10); // 设置深度,确保显示在侧边栏上方
|
||||||
|
|
||||||
|
const key3Text = this.add.text(10, 160, '按3键:创建工具类物品', {
|
||||||
|
fontSize: '16px',
|
||||||
|
fill: '#ffffff'
|
||||||
|
});
|
||||||
|
key3Text.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
key3Text.setDepth(10); // 设置深度,确保显示在侧边栏上方
|
||||||
|
|
||||||
|
const key4Text = this.add.text(10, 190, '按4键:清理所有物品', {
|
||||||
|
fontSize: '16px',
|
||||||
|
fill: '#ffffff'
|
||||||
|
});
|
||||||
|
key4Text.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
key4Text.setDepth(10); // 设置深度,确保显示在侧边栏上方
|
||||||
|
|
||||||
|
const spaceText = this.add.text(10, 220, '按空格键返回启动场景', {
|
||||||
|
fontSize: '16px',
|
||||||
|
fill: '#ffffff'
|
||||||
|
});
|
||||||
|
spaceText.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
spaceText.setDepth(10); // 设置深度,确保显示在侧边栏上方
|
||||||
|
|
||||||
|
// 显示单位状态
|
||||||
|
this.updateUnitStatus(unit);
|
||||||
|
|
||||||
|
// 显示默认提示
|
||||||
|
this.itemInfoText.setText('未选择任何物品');
|
||||||
|
this.interactionText.setText('点击物品查看详细信息,交互范围50像素');
|
||||||
|
this.generalInfoText.setText('欢迎使用物品系统测试场景');
|
||||||
|
|
||||||
|
// 添加场景提示信息
|
||||||
|
const interactionHintText = this.add.text(10, 250, '点击物品查看详细信息,交互范围50像素', {
|
||||||
|
fontSize: '16px',
|
||||||
|
fill: '#ffffff'
|
||||||
|
});
|
||||||
|
interactionHintText.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
interactionHintText.setDepth(10); // 设置深度,确保显示在侧边栏上方
|
||||||
|
|
||||||
|
// 注册键盘事件
|
||||||
|
this.input.keyboard.on('keydown-ONE', () => {
|
||||||
|
this.itemManager.createRandomItem();
|
||||||
|
});
|
||||||
|
|
||||||
|
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.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.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.createButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建初始物品
|
||||||
|
*/
|
||||||
|
createInitialItems() {
|
||||||
|
// 在不同位置创建各种类型的物品
|
||||||
|
const itemTypes = ['food', 'tool', 'medical', 'weapon'];
|
||||||
|
const unit = this.unitGroup.getFirstAlive();
|
||||||
|
|
||||||
|
for (let i = 0; i < itemTypes.length; i++) {
|
||||||
|
const x = unit.x + (i - 2) * 200;
|
||||||
|
const y = unit.y - 200;
|
||||||
|
this.itemManager.createItemByType(itemTypes[i], x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建交互按钮
|
||||||
|
*/
|
||||||
|
createButtons() {
|
||||||
|
const buttonWidth = 200;
|
||||||
|
const buttonHeight = 40;
|
||||||
|
const buttonY = this.sys.game.config.height - 100;
|
||||||
|
|
||||||
|
// 创建随机物品按钮
|
||||||
|
this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY, '创建随机物品', () => {
|
||||||
|
this.itemManager.createRandomItem();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 创建清理物品按钮
|
||||||
|
this.createButton(this.sys.game.config.width - buttonWidth - 10, buttonY + 50, '清理所有物品', () => {
|
||||||
|
this.itemManager.clearAllItems();
|
||||||
|
this.itemInfoText.setText('所有物品已清理');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建按钮
|
||||||
|
* @param {number} x - 按钮x坐标
|
||||||
|
* @param {number} y - 按钮y坐标
|
||||||
|
* @param {string} text - 按钮文本
|
||||||
|
* @param {function} callback - 点击回调函数
|
||||||
|
*/
|
||||||
|
createButton(x, y, text, callback) {
|
||||||
|
// 创建按钮背景
|
||||||
|
const button = this.add.rectangle(x, y, 200, 40, 0x333333);
|
||||||
|
button.setOrigin(0.5, 0.5);
|
||||||
|
button.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
button.setDepth(15); // 设置深度,确保显示在场景说明文本上方
|
||||||
|
|
||||||
|
// 创建按钮文本
|
||||||
|
const buttonText = this.add.text(x, y, text, {
|
||||||
|
fontSize: '16px',
|
||||||
|
fill: '#ffffff',
|
||||||
|
fontFamily: 'Arial'
|
||||||
|
});
|
||||||
|
buttonText.setOrigin(0.5, 0.5);
|
||||||
|
buttonText.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
buttonText.setDepth(16); // 设置深度,确保显示在按钮背景上方
|
||||||
|
|
||||||
|
// 设置按钮交互
|
||||||
|
button.setInteractive({
|
||||||
|
useHandCursor: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// 按钮事件
|
||||||
|
button.on('pointerdown', callback);
|
||||||
|
|
||||||
|
button.on('pointerover', () => {
|
||||||
|
button.setFillStyle(0x555555);
|
||||||
|
});
|
||||||
|
|
||||||
|
button.on('pointerout', () => {
|
||||||
|
button.setFillStyle(0x333333);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示物品信息
|
||||||
|
* @param {Item} item - 物品实例
|
||||||
|
*/
|
||||||
|
showItemInfo(item) {
|
||||||
|
const unit = this.unitGroup.getFirstAlive();
|
||||||
|
const isInRange = item.isInInteractionRange(unit);
|
||||||
|
|
||||||
|
const info = item.getInfo();
|
||||||
|
let infoText = `${info.name}\n`;
|
||||||
|
infoText += `${info.description}\n`;
|
||||||
|
infoText += `类型: ${info.type}\n`;
|
||||||
|
infoText += `重量: ${info.weight}kg\n`;
|
||||||
|
infoText += `体积: ${info.volume}L\n`;
|
||||||
|
infoText += `价值: ${info.value}金币\n`;
|
||||||
|
infoText += `距离: ${Math.round(Math.sqrt(Math.pow(item.x - unit.x, 2) + Math.pow(item.y - unit.y, 2)))}m\n`;
|
||||||
|
|
||||||
|
// 显示物品属性
|
||||||
|
infoText += '属性: ';
|
||||||
|
const properties = [];
|
||||||
|
for (const [key, value] of Object.entries(info.properties)) {
|
||||||
|
properties.push(`${key}: ${value}`);
|
||||||
|
}
|
||||||
|
infoText += properties.join(', ');
|
||||||
|
|
||||||
|
this.itemInfoText.setText(infoText);
|
||||||
|
|
||||||
|
// 显示交互提示
|
||||||
|
if (isInRange) {
|
||||||
|
this.interactionText.setText('按E键拾取物品,按Q键快捷使用');
|
||||||
|
// 注册E键拾取物品
|
||||||
|
this.input.keyboard.once('keydown-E', () => {
|
||||||
|
item.pickup(unit);
|
||||||
|
this.interactionText.setText('');
|
||||||
|
this.itemInfoText.setText('未选择任何物品');
|
||||||
|
});
|
||||||
|
// 注册Q键快捷使用物品
|
||||||
|
this.input.keyboard.once('keydown-Q', () => {
|
||||||
|
item.use(unit);
|
||||||
|
this.interactionText.setText('');
|
||||||
|
this.itemInfoText.setText('未选择任何物品');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.interactionText.setText('距离太远,无法交互');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除5秒后自动清除的逻辑,让信息保持显示
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建侧边栏UI
|
||||||
|
*/
|
||||||
|
createSidebar() {
|
||||||
|
// 侧边栏宽度
|
||||||
|
const sidebarWidth = 300;
|
||||||
|
const sidebarDepth = 5; // 侧边栏深度值,确保显示在游戏元素上方,但低于场景说明文本
|
||||||
|
|
||||||
|
// 创建侧边栏背景
|
||||||
|
this.sidebar = this.add.rectangle(
|
||||||
|
this.sys.game.config.width - sidebarWidth,
|
||||||
|
0,
|
||||||
|
sidebarWidth,
|
||||||
|
this.sys.game.config.height,
|
||||||
|
0x111111,
|
||||||
|
0.9
|
||||||
|
);
|
||||||
|
this.sidebar.setOrigin(0, 0);
|
||||||
|
this.sidebar.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
this.sidebar.setDepth(sidebarDepth); // 设置深度,确保显示在游戏元素上方
|
||||||
|
|
||||||
|
// 添加侧边栏边框
|
||||||
|
this.sidebarBorder = this.add.rectangle(
|
||||||
|
this.sys.game.config.width - sidebarWidth,
|
||||||
|
0,
|
||||||
|
sidebarWidth,
|
||||||
|
this.sys.game.config.height,
|
||||||
|
0x444444,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
this.sidebarBorder.setOrigin(0, 0);
|
||||||
|
this.sidebarBorder.setStrokeStyle(2, 0x444444, 1);
|
||||||
|
this.sidebarBorder.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
this.sidebarBorder.setDepth(sidebarDepth + 1); // 设置深度,确保显示在侧边栏背景上方
|
||||||
|
|
||||||
|
// 侧边栏标题
|
||||||
|
const title = this.add.text(
|
||||||
|
this.sys.game.config.width - sidebarWidth + 20,
|
||||||
|
20,
|
||||||
|
'游戏信息面板',
|
||||||
|
{
|
||||||
|
fontSize: '20px',
|
||||||
|
fill: '#ffffff',
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
title.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
title.setDepth(sidebarDepth + 2); // 设置深度,确保显示在侧边栏边框上方
|
||||||
|
|
||||||
|
// 通用信息区域标题
|
||||||
|
const generalTitle = this.add.text(
|
||||||
|
this.sys.game.config.width - sidebarWidth + 20,
|
||||||
|
50,
|
||||||
|
'通用信息:',
|
||||||
|
{
|
||||||
|
fontSize: '16px',
|
||||||
|
fill: '#4CAF50',
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
generalTitle.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
generalTitle.setDepth(sidebarDepth + 2); // 设置深度,确保显示在侧边栏边框上方
|
||||||
|
|
||||||
|
this.generalInfoText = this.add.text(
|
||||||
|
this.sys.game.config.width - sidebarWidth + 20,
|
||||||
|
75,
|
||||||
|
'',
|
||||||
|
{
|
||||||
|
fontSize: '14px',
|
||||||
|
fill: '#ffffff',
|
||||||
|
wordWrap: {
|
||||||
|
width: sidebarWidth - 40
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this.generalInfoText.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
this.generalInfoText.setDepth(sidebarDepth + 2); // 设置深度,确保显示在侧边栏边框上方
|
||||||
|
|
||||||
|
// 角色属性区域标题
|
||||||
|
const characterTitle = this.add.text(
|
||||||
|
this.sys.game.config.width - sidebarWidth + 20,
|
||||||
|
120,
|
||||||
|
'角色属性:',
|
||||||
|
{
|
||||||
|
fontSize: '16px',
|
||||||
|
fill: '#2196F3',
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
characterTitle.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
characterTitle.setDepth(sidebarDepth + 2); // 设置深度,确保显示在侧边栏边框上方
|
||||||
|
|
||||||
|
this.unitStatusText = this.add.text(
|
||||||
|
this.sys.game.config.width - sidebarWidth + 20,
|
||||||
|
145,
|
||||||
|
'',
|
||||||
|
{
|
||||||
|
fontSize: '14px',
|
||||||
|
fill: '#ffffff',
|
||||||
|
wordWrap: {
|
||||||
|
width: sidebarWidth - 40
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this.unitStatusText.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
this.unitStatusText.setDepth(sidebarDepth + 2); // 设置深度,确保显示在侧边栏边框上方
|
||||||
|
|
||||||
|
// 交互提示区域标题
|
||||||
|
const interactionTitle = this.add.text(
|
||||||
|
this.sys.game.config.width - sidebarWidth + 20,
|
||||||
|
220,
|
||||||
|
'交互提示:',
|
||||||
|
{
|
||||||
|
fontSize: '16px',
|
||||||
|
fill: '#FFEB3B',
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
interactionTitle.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
interactionTitle.setDepth(sidebarDepth + 2); // 设置深度,确保显示在侧边栏边框上方
|
||||||
|
|
||||||
|
this.interactionText = this.add.text(
|
||||||
|
this.sys.game.config.width - sidebarWidth + 20,
|
||||||
|
245,
|
||||||
|
'',
|
||||||
|
{
|
||||||
|
fontSize: '14px',
|
||||||
|
fill: '#ffff00',
|
||||||
|
wordWrap: {
|
||||||
|
width: sidebarWidth - 40
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this.interactionText.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
this.interactionText.setDepth(sidebarDepth + 2); // 设置深度,确保显示在侧边栏边框上方
|
||||||
|
|
||||||
|
// 物品详情区域标题
|
||||||
|
const itemTitle = this.add.text(
|
||||||
|
this.sys.game.config.width - sidebarWidth + 20,
|
||||||
|
350,
|
||||||
|
'物品详情:',
|
||||||
|
{
|
||||||
|
fontSize: '16px',
|
||||||
|
fill: '#FF9800',
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
itemTitle.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
itemTitle.setDepth(sidebarDepth + 2); // 设置深度,确保显示在侧边栏边框上方
|
||||||
|
|
||||||
|
this.itemInfoText = this.add.text(
|
||||||
|
this.sys.game.config.width - sidebarWidth + 20,
|
||||||
|
375,
|
||||||
|
'',
|
||||||
|
{
|
||||||
|
fontSize: '14px',
|
||||||
|
fill: '#ffffff',
|
||||||
|
wordWrap: {
|
||||||
|
width: sidebarWidth - 40
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this.itemInfoText.setScrollFactor(0, 0); // 固定在屏幕上,不随相机移动
|
||||||
|
this.itemInfoText.setDepth(sidebarDepth + 2); // 设置深度,确保显示在侧边栏边框上方
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新单位状态显示
|
||||||
|
* @param {Unit} unit - 单位实例
|
||||||
|
*/
|
||||||
|
updateUnitStatus(unit) {
|
||||||
|
let statusText = `${unit.name} 状态:\n`;
|
||||||
|
statusText += `生命值: ${unit.health}\n`;
|
||||||
|
statusText += `营养值: ${unit.nutrition}\n`;
|
||||||
|
statusText += `水分值: ${unit.hydration}\n`;
|
||||||
|
if (unit.weapon) {
|
||||||
|
statusText += `武器: ${unit.weapon.name}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.unitStatusText.setText(statusText);
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this.inputSystem.update();
|
||||||
|
|
||||||
|
// 更新所有单位
|
||||||
|
this.unitGroup.getChildren().forEach(unit => {
|
||||||
|
if (unit.update) {
|
||||||
|
unit.update();
|
||||||
|
}
|
||||||
|
unit.updateMovement();
|
||||||
|
// 更新单位状态显示
|
||||||
|
this.updateUnitStatus(unit);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user