mirror of
http://junepve.top:3000/chicrobot/CINC.git
synced 2026-10-30 07:31:29 +08:00
560 lines
21 KiB
JavaScript
560 lines
21 KiB
JavaScript
// 输入系统:处理玩家的键盘、鼠标和触摸输入,将输入转换为游戏事件
|
|
|
|
// 从ControlMode.js导入清除选择和设置激活单位的函数
|
|
import { clearSelection, setActiveUnit } from './ControlMode.js';
|
|
|
|
// 导出InputSystem类,用于创建输入系统实例
|
|
export class InputSystem {
|
|
// 构造函数:初始化输入系统
|
|
// @param {Object} scene - 游戏场景实例
|
|
// @param {Object} config - 输入配置选项
|
|
constructor(scene, config = {}) {
|
|
// 保存场景引用,用于访问游戏世界和发送事件
|
|
this.scene = scene;
|
|
|
|
// 用于存储框选开始时的鼠标世界坐标
|
|
// 初始值为null,表示当前没有进行框选操作
|
|
this.selectionStart = null;
|
|
|
|
// 移动方式开关配置
|
|
this.enabledModes = {
|
|
keyboard: config.keyboard !== false, // 键盘控制
|
|
mouse: config.mouse !== false, // 鼠标点击移动
|
|
joystick: config.joystick !== false, // 虚拟摇杆控制
|
|
selection: config.selection !== false // 框选功能
|
|
};
|
|
|
|
// 初始化键盘输入
|
|
// 获取Phaser的键盘输入管理器
|
|
const kb = scene.input.keyboard;
|
|
|
|
// 创建按键映射对象,将游戏功能与键盘按键关联
|
|
this.keys = {
|
|
// 上移键:同时支持W键和方向上键
|
|
up: [kb.addKey(Phaser.Input.Keyboard.KeyCodes.W), kb.addKey(Phaser.Input.Keyboard.KeyCodes.UP)],
|
|
// 下移键:同时支持S键和方向下键
|
|
down: [kb.addKey(Phaser.Input.Keyboard.KeyCodes.S), kb.addKey(Phaser.Input.Keyboard.KeyCodes.DOWN)],
|
|
// 左移键:同时支持A键和方向左键
|
|
left: [kb.addKey(Phaser.Input.Keyboard.KeyCodes.A), kb.addKey(Phaser.Input.Keyboard.KeyCodes.LEFT)],
|
|
// 右移键:同时支持D键和方向右键
|
|
right: [kb.addKey(Phaser.Input.Keyboard.KeyCodes.D), kb.addKey(Phaser.Input.Keyboard.KeyCodes.RIGHT)]
|
|
};
|
|
|
|
// 添加F键快捷拾取功能
|
|
this.fKey = kb.addKey(Phaser.Input.Keyboard.KeyCodes.F);
|
|
this.fKey.on('down', () => {
|
|
this.handleQuickPickup();
|
|
});
|
|
|
|
// 禁用浏览器右键菜单,避免影响游戏操作
|
|
scene.input.mouse.disableContextMenu();
|
|
|
|
// 注册鼠标/触摸事件监听器
|
|
// 当鼠标/触摸按下时,调用onPointerDown方法
|
|
scene.input.on('pointerdown', this.onPointerDown, this);
|
|
// 当鼠标/触摸移动时,调用onPointerMove方法
|
|
scene.input.on('pointermove', this.onPointerMove, this);
|
|
// 当鼠标/触摸释放时,调用onPointerUp方法
|
|
scene.input.on('pointerup', this.onPointerUp, this);
|
|
}
|
|
|
|
// 检查按键组中是否有任何按键被按下
|
|
// @param {Array} keyGroup - 按键对象数组
|
|
// @returns {boolean} - 如果有任何按键被按下则返回true,否则返回false
|
|
isKeyDown(keyGroup) {
|
|
// 使用some方法检查数组中是否有任何一个按键处于按下状态
|
|
return keyGroup.some(key => key.isDown);
|
|
}
|
|
|
|
// update方法:每帧自动调用(约60次/秒),用于处理持续的输入
|
|
update() {
|
|
// 只有在键盘模式启用时才处理键盘输入
|
|
if (this.enabledModes.keyboard) {
|
|
// 创建一个方向对象,用于存储移动方向
|
|
const dir = { x: 0, y: 0 };
|
|
|
|
// 检查左移键是否被按下,如果是则x方向减1(向左移动)
|
|
if (this.isKeyDown(this.keys.left)) dir.x -= 1;
|
|
// 检查右移键是否被按下,如果是则x方向加1(向右移动)
|
|
if (this.isKeyDown(this.keys.right)) dir.x += 1;
|
|
// 检查上移键是否被按下,如果是则y方向减1(向上移动)
|
|
if (this.isKeyDown(this.keys.up)) dir.y -= 1;
|
|
// 检查下移键是否被按下,如果是则y方向加1(向下移动)
|
|
if (this.isKeyDown(this.keys.down)) dir.y += 1;
|
|
|
|
// 无论是否有按键按下,都发送移动事件
|
|
// 当dir.x和dir.y都为0时,单位会停止移动
|
|
this.scene.events.emit('move-relative', dir);
|
|
}
|
|
}
|
|
|
|
// 处理鼠标/触摸按下事件
|
|
// @param {Object} pointer - 指针事件对象,包含鼠标/触摸的位置等信息
|
|
onPointerDown(pointer) {
|
|
// 检查鼠标是否在UI元素上,如果是则不处理
|
|
if (this.isMouseOnUI(pointer)) {
|
|
return;
|
|
}
|
|
|
|
// 如果是左键按下
|
|
if (pointer.leftButtonDown()) {
|
|
// 获取鼠标在游戏世界中的坐标(不是屏幕坐标)
|
|
const worldX = pointer.worldX;
|
|
const worldY = pointer.worldY;
|
|
|
|
// 检查是否点中了某个单位
|
|
let clickedUnit = null;
|
|
// 遍历场景中的所有单位
|
|
this.scene.unitGroup.getChildren().forEach(unit => {
|
|
// 获取单位的边界矩形
|
|
const bounds = unit.getBounds();
|
|
// 检查鼠标世界坐标是否在单位的边界内
|
|
if (worldX >= bounds.x && worldX <= bounds.right &&
|
|
worldY >= bounds.y && worldY <= bounds.bottom) {
|
|
// 如果点中了单位,存储该单位
|
|
clickedUnit = unit;
|
|
}
|
|
});
|
|
|
|
// 检查是否点中了某个物品
|
|
let clickedItem = null;
|
|
// 遍历场景中的所有物品
|
|
if (this.scene.itemManager && this.scene.itemManager.getActiveItems) {
|
|
this.scene.itemManager.getActiveItems().forEach(item => {
|
|
// 获取物品的边界矩形
|
|
const bounds = item.getBounds();
|
|
// 检查鼠标世界坐标是否在物品的边界内
|
|
if (worldX >= bounds.x && worldX <= bounds.right &&
|
|
worldY >= bounds.y && worldY <= bounds.bottom) {
|
|
// 如果点中了物品,存储该物品
|
|
clickedItem = item;
|
|
}
|
|
});
|
|
}
|
|
|
|
if (clickedUnit) {
|
|
// 如果点中了单位,发送选择单位事件
|
|
this.scene.events.emit('select-unit', clickedUnit);
|
|
// 存储点击位置,用于判断是否是拖动操作
|
|
this.dragStart = { x: worldX, y: worldY, clickedUnit: clickedUnit };
|
|
// 不设置selectionStart,避免触发框选
|
|
this.selectionStart = null;
|
|
} else if (clickedItem) {
|
|
// 如果点中了物品,不执行后续操作,避免触发移动
|
|
this.selectionStart = null;
|
|
this.dragStart = null;
|
|
} 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 && !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;
|
|
}
|
|
}
|
|
|
|
// 处理鼠标/触摸移动事件
|
|
// @param {Object} pointer - 指针事件对象
|
|
onPointerMove(pointer) {
|
|
// 检查鼠标是否在UI元素上,如果是则不处理
|
|
if (this.isMouseOnUI(pointer)) {
|
|
return;
|
|
}
|
|
|
|
// 如果当前正在进行框选操作且框选功能启用
|
|
if (this.selectionStart && this.enabledModes.selection) {
|
|
// 获取当前鼠标在游戏世界中的坐标
|
|
const currentWorldX = pointer.worldX;
|
|
const currentWorldY = pointer.worldY;
|
|
|
|
// 计算框选区域的矩形
|
|
// 确保矩形的x和y是左上角坐标
|
|
const rect = new Phaser.Geom.Rectangle(
|
|
// 使用Math.min确保x是较小的值(左上角)
|
|
Math.min(this.selectionStart.x, currentWorldX),
|
|
// 使用Math.min确保y是较小的值(左上角)
|
|
Math.min(this.selectionStart.y, currentWorldY),
|
|
// 计算矩形宽度
|
|
Math.abs(currentWorldX - this.selectionStart.x),
|
|
// 计算矩形高度
|
|
Math.abs(currentWorldY - this.selectionStart.y)
|
|
);
|
|
|
|
// 只有当框选区域足够大时才发送选择更新事件
|
|
if (rect.width > 5 || rect.height > 5) {
|
|
// 发送选择更新事件,更新框选区域的显示
|
|
this.scene.events.emit('selection-start', this.selectionStart);
|
|
this.scene.events.emit('selection-update', rect);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 处理鼠标/触摸释放事件
|
|
// @param {Object} pointer - 指针事件对象
|
|
onPointerUp(pointer) {
|
|
// 检查鼠标是否在UI元素上,如果是则不处理
|
|
if (this.isMouseOnUI(pointer)) {
|
|
// 重置框选起始点和拖动状态
|
|
this.selectionStart = null;
|
|
this.dragStart = null;
|
|
return;
|
|
}
|
|
|
|
// 处理拖动单位的逻辑
|
|
if (this.dragStart) {
|
|
// 获取当前鼠标在游戏世界中的坐标
|
|
const currentWorldX = pointer.worldX;
|
|
const currentWorldY = pointer.worldY;
|
|
|
|
// 计算拖动距离
|
|
const dx = currentWorldX - this.dragStart.x;
|
|
const dy = currentWorldY - this.dragStart.y;
|
|
const dragDistance = Math.sqrt(dx * dx + dy * dy);
|
|
|
|
// 如果拖动距离超过阈值(10像素),视为拖动操作
|
|
if (dragDistance > 10 && this.enabledModes.mouse && !this.isInPlantingMode()) {
|
|
// 发送移动到指定点的事件,让单位移动到释放位置
|
|
this.scene.events.emit('move-to-point', currentWorldX, currentWorldY);
|
|
}
|
|
|
|
// 重置拖动状态
|
|
this.dragStart = null;
|
|
}
|
|
// 如果当前正在进行框选操作且框选功能启用
|
|
else if (this.selectionStart && this.enabledModes.selection) {
|
|
// 获取当前鼠标在游戏世界中的坐标
|
|
const currentWorldX = pointer.worldX;
|
|
const currentWorldY = pointer.worldY;
|
|
|
|
// 计算最终的框选区域
|
|
const rect = new Phaser.Geom.Rectangle(
|
|
Math.min(this.selectionStart.x, currentWorldX),
|
|
Math.min(this.selectionStart.y, currentWorldY),
|
|
Math.abs(currentWorldX - this.selectionStart.x),
|
|
Math.abs(currentWorldY - this.selectionStart.y)
|
|
);
|
|
|
|
// 如果框选区域太小(宽度和高度都小于10像素),视为点击地面移动
|
|
if (rect.width < 10 && rect.height < 10 && this.enabledModes.mouse && !this.isInPlantingMode()) {
|
|
// 发送移动到指定点的事件(仅在鼠标模式启用时,且不在种植模式下)
|
|
this.scene.events.emit('move-to-point', pointer.worldX, pointer.worldY);
|
|
} else {
|
|
// 否则执行框选操作
|
|
this.scene.events.emit('selection-end', rect);
|
|
}
|
|
|
|
// 重置框选起始点,结束框选操作
|
|
this.selectionStart = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 检查鼠标是否在小地图上
|
|
* @param {Phaser.Input.Pointer} pointer - 指针事件对象
|
|
* @returns {boolean} - 如果鼠标在小地图上返回true,否则返回false
|
|
*/
|
|
isMouseOnMiniMap(pointer) {
|
|
// 检查场景中是否有小地图
|
|
if (!this.scene.miniMap) {
|
|
return false;
|
|
}
|
|
|
|
// 获取小地图实例
|
|
const miniMap = this.scene.miniMap;
|
|
// 获取鼠标在屏幕上的坐标
|
|
const mouseX = pointer.x;
|
|
const mouseY = pointer.y;
|
|
|
|
// 计算小地图的边界(包括锁定按钮区域)
|
|
const mapLeft = miniMap.x; // 小地图左边界
|
|
const mapRight = miniMap.x + miniMap.mapSize; // 小地图右边界
|
|
const mapTop = miniMap.y; // 小地图上边界
|
|
// 小地图下边界,包括锁定按钮(按钮高度25,边距5)
|
|
const mapBottom = miniMap.y + miniMap.mapSize + 30;
|
|
|
|
// 检查鼠标坐标是否在小地图边界内
|
|
return mouseX >= mapLeft && mouseX <= mapRight &&
|
|
mouseY >= mapTop && mouseY <= mapBottom;
|
|
}
|
|
|
|
/**
|
|
* 检查鼠标是否在UI元素上
|
|
* @param {Phaser.Input.Pointer} pointer - 指针事件对象
|
|
* @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.isMouseOnSkillWheel(pointer) ||
|
|
this.isMouseOnSidebar(pointer) ||
|
|
this.isMouseOnInventoryUI(pointer) ||
|
|
this.isMouseOnItemListUI(pointer);
|
|
}
|
|
|
|
/**
|
|
* 检查鼠标是否在技能轮盘上
|
|
* @param {Object} pointer - 指针事件对象
|
|
* @returns {boolean} - 如果鼠标在技能轮盘上返回true,否则返回false
|
|
*/
|
|
isMouseOnSkillWheel(pointer) {
|
|
// 检查场景中是否有技能轮盘
|
|
if (!this.scene.skillWheel) {
|
|
return false;
|
|
}
|
|
|
|
// 获取技能轮盘实例
|
|
const skillWheel = this.scene.skillWheel;
|
|
// 获取鼠标在屏幕上的坐标
|
|
const mouseX = pointer.x;
|
|
const mouseY = pointer.y;
|
|
|
|
// 计算技能轮盘的边界(包括轮盘和操作区域)
|
|
const skillWheelRadius = skillWheel.radius * 3; // 操作区域是轮盘半径的三倍,考虑技能按钮的位置
|
|
const skillWheelLeft = skillWheel.centerX - skillWheelRadius; // 轮盘左边界
|
|
const skillWheelRight = skillWheel.centerX + skillWheelRadius; // 轮盘右边界
|
|
const skillWheelTop = skillWheel.centerY - skillWheelRadius; // 轮盘上边界
|
|
const skillWheelBottom = skillWheel.centerY + skillWheelRadius; // 轮盘下边界
|
|
|
|
// 检查鼠标是否在操作区域内
|
|
if (mouseX >= skillWheelLeft && mouseX <= skillWheelRight &&
|
|
mouseY >= skillWheelTop && mouseY <= skillWheelBottom) {
|
|
return true;
|
|
}
|
|
|
|
// 检查是否点击在技能按钮上
|
|
for (const button of skillWheel.skillButtons) {
|
|
const buttonBounds = button.getBounds();
|
|
if (mouseX >= buttonBounds.x && mouseX <= buttonBounds.right &&
|
|
mouseY >= buttonBounds.y && mouseY <= buttonBounds.bottom) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* 检查当前是否处于种植或收获模式
|
|
* @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 - 指针事件对象
|
|
* @returns {boolean} - 如果鼠标在物品列表菜单上返回true,否则返回false
|
|
*/
|
|
isMouseOnItemListUI(pointer) {
|
|
// 检查场景中是否有物品列表UI
|
|
if (!this.scene.itemListUI) {
|
|
return false;
|
|
}
|
|
|
|
// 获取物品列表UI实例
|
|
const itemListUI = this.scene.itemListUI;
|
|
// 获取鼠标在屏幕上的坐标
|
|
const mouseX = pointer.x;
|
|
const mouseY = pointer.y;
|
|
|
|
// 检查UI是否可见
|
|
if (!itemListUI.visible) {
|
|
return false;
|
|
}
|
|
|
|
// 直接使用UI的位置和尺寸来计算边界,不依赖container
|
|
const uiX = itemListUI.x;
|
|
const uiY = itemListUI.y;
|
|
const uiWidth = itemListUI.width;
|
|
const uiHeight = itemListUI.height;
|
|
|
|
// 检查鼠标坐标是否在物品列表UI边界内
|
|
return mouseX >= uiX && mouseX <= uiX + uiWidth &&
|
|
mouseY >= uiY && mouseY <= uiY + uiHeight;
|
|
}
|
|
|
|
/**
|
|
* 检查鼠标是否在虚拟摇杆上
|
|
* @param {Phaser.Input.Pointer} pointer - 指针事件对象
|
|
* @returns {boolean} - 如果鼠标在摇杆上返回true,否则返回false
|
|
*/
|
|
isMouseOnJoystick(pointer) {
|
|
// 检查场景中是否有虚拟摇杆
|
|
if (!this.scene.virtualJoystick) {
|
|
return false;
|
|
}
|
|
|
|
// 获取虚拟摇杆实例
|
|
const joystick = this.scene.virtualJoystick;
|
|
// 获取鼠标在屏幕上的坐标
|
|
const mouseX = pointer.x;
|
|
const mouseY = pointer.y;
|
|
|
|
// 计算摇杆的边界(包括摇杆和操作区域)
|
|
const joystickRadius = joystick.radius * 2; // 操作区域是摇杆半径的两倍
|
|
const joystickLeft = joystick.centerX - joystickRadius; // 摇杆左边界
|
|
const joystickRight = joystick.centerX + joystickRadius; // 摇杆右边界
|
|
const joystickTop = joystick.centerY - joystickRadius; // 摇杆上边界
|
|
const joystickBottom = joystick.centerY + joystickRadius; // 摇杆下边界
|
|
|
|
// 检查鼠标坐标是否在摇杆边界内
|
|
return mouseX >= joystickLeft && mouseX <= joystickRight &&
|
|
mouseY >= joystickTop && mouseY <= joystickBottom;
|
|
}
|
|
|
|
/**
|
|
* 检查相机是否被锁定到某个角色
|
|
* @returns {boolean} - 如果相机被锁定返回true,否则返回false
|
|
*/
|
|
isCameraLocked() {
|
|
// 检查ControlMode模块是否存在且cameraLocked属性已定义
|
|
if (typeof window !== 'undefined' && window.cameraLocked !== undefined) {
|
|
return window.cameraLocked;
|
|
}
|
|
|
|
// 检查场景中是否有小地图且处于锁定状态
|
|
if (this.scene.miniMap && this.scene.miniMap.isLocked) {
|
|
return this.scene.miniMap.isLocked;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* 检查鼠标是否在侧边栏上
|
|
* @param {Phaser.Input.Pointer} pointer - 指针事件对象
|
|
* @returns {boolean} - 如果鼠标在侧边栏上返回true,否则返回false
|
|
*/
|
|
isMouseOnSidebar(pointer) {
|
|
// 检查场景中是否有侧边栏
|
|
if (!this.scene.sidebar) {
|
|
return false;
|
|
}
|
|
|
|
// 获取侧边栏实例
|
|
const sidebar = this.scene.sidebar;
|
|
// 获取鼠标在屏幕上的坐标
|
|
const mouseX = pointer.x;
|
|
const mouseY = pointer.y;
|
|
|
|
// 获取侧边栏的边界
|
|
const bounds = sidebar.getBounds();
|
|
|
|
// 检查鼠标坐标是否在侧边栏边界内
|
|
return mouseX >= bounds.x && mouseX <= bounds.right &&
|
|
mouseY >= bounds.y && mouseY <= bounds.bottom;
|
|
}
|
|
|
|
/**
|
|
* 检查鼠标是否在背包UI上
|
|
* @param {Phaser.Input.Pointer} pointer - 指针事件对象
|
|
* @returns {boolean} - 如果鼠标在背包UI上返回true,否则返回false
|
|
*/
|
|
isMouseOnInventoryUI(pointer) {
|
|
// 检查场景中是否有背包UI
|
|
if (!this.scene.inventoryUI) {
|
|
return false;
|
|
}
|
|
|
|
// 获取背包UI实例
|
|
const inventoryUI = this.scene.inventoryUI;
|
|
// 获取鼠标在屏幕上的坐标
|
|
const mouseX = pointer.x;
|
|
const mouseY = pointer.y;
|
|
|
|
// 获取背包UI的边界
|
|
const container = inventoryUI.container;
|
|
if (!container) {
|
|
return false;
|
|
}
|
|
|
|
const containerBounds = container.getBounds();
|
|
|
|
// 检查鼠标坐标是否在背包UI边界内
|
|
return mouseX >= containerBounds.x && mouseX <= containerBounds.right &&
|
|
mouseY >= containerBounds.y && mouseY <= containerBounds.bottom;
|
|
}
|
|
|
|
/**
|
|
* 处理F键快捷拾取功能
|
|
*/
|
|
handleQuickPickup() {
|
|
console.log('handleQuickPickup: 尝试快捷拾取物品');
|
|
|
|
// 确保场景中有玩家和物品管理器
|
|
if (!this.scene.player || !this.scene.itemManager) {
|
|
console.log('handleQuickPickup: 缺少玩家或物品管理器');
|
|
return;
|
|
}
|
|
|
|
const player = this.scene.player;
|
|
const itemManager = this.scene.itemManager;
|
|
|
|
// 获取所有活动物品
|
|
const activeItems = itemManager.getActiveItems ? itemManager.getActiveItems() : [];
|
|
if (activeItems.length === 0) {
|
|
console.log('handleQuickPickup: 没有可拾取的物品');
|
|
return;
|
|
}
|
|
|
|
const pickupDistance = 50; // 最大拾取距离,与物品交互距离保持一致
|
|
let closestItem = null;
|
|
let minDistance = pickupDistance;
|
|
|
|
// 找到距离玩家最近且在拾取范围内的物品
|
|
activeItems.forEach(item => {
|
|
// 计算物品与玩家的距离
|
|
const dx = item.x - player.x;
|
|
const dy = item.y - player.y;
|
|
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
|
|
// 如果物品在拾取范围内且距离更近,更新最近物品
|
|
if (distance < minDistance) {
|
|
minDistance = distance;
|
|
closestItem = item;
|
|
}
|
|
});
|
|
|
|
// 如果找到最近物品,尝试拾取
|
|
if (closestItem) {
|
|
console.log(`handleQuickPickup: 拾取距离最近的物品: ${closestItem.name},距离: ${Math.round(minDistance)}`);
|
|
closestItem.pickup(player);
|
|
|
|
// 更新背包UI,确保物品立即显示在背包中
|
|
if (this.scene.inventoryUI) {
|
|
this.scene.inventoryUI.updateUI();
|
|
}
|
|
} else {
|
|
console.log('handleQuickPickup: 没有在拾取范围内的物品');
|
|
}
|
|
}
|
|
} |