feat(item) 优化移动及添加测试场景

This commit is contained in:
chicrobot committed 2026-01-04 00:55:48 +08:00
1 parent 2f7210f47e
commit b9a5180293
15 files changed
+1428 -62

No files matched your search

+145 -38
View File
@@ -7,7 +7,8 @@ import { clearSelection, setActiveUnit } from './ControlMode.js';
export class InputSystem {
// 构造函数:初始化输入系统
// @param {Object} scene - 游戏场景实例
constructor(scene) {
// @param {Object} config - 输入配置选项
constructor(scene, config = {}) {
// 保存场景引用,用于访问游戏世界和发送事件
this.scene = scene;
@@ -15,6 +16,14 @@ export class InputSystem {
// 初始值为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;
@@ -53,28 +62,31 @@ export class InputSystem {
// update方法:每帧自动调用(约60次/秒),用于处理持续的输入
update() {
// 创建一个方向对象,用于存储移动方向
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;
// 只有在键盘模式启用时才处理键盘输入
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);
// 无论是否有按键按下,都发送移动事件
// 当dir.x和dir.y都为0时,单位会停止移动
this.scene.events.emit('move-relative', dir);
}
}
// 处理鼠标/触摸按下事件
// @param {Object} pointer - 指针事件对象,包含鼠标/触摸的位置等信息
onPointerDown(pointer) {
// 检查鼠标是否在小地图或摇杆上,如果是则不处理框选
if (this.isMouseOnMiniMap(pointer) || this.isMouseOnJoystick(pointer)) {
// 检查鼠标是否在小地图、摇杆或侧边栏上,如果是则不处理
if (this.isMouseOnMiniMap(pointer) || this.isMouseOnJoystick(pointer) || this.isMouseOnSidebar(pointer)) {
return;
}
@@ -98,34 +110,60 @@ export class InputSystem {
}
});
// 检查是否点中了某个物品
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);
} else {
// 如果没有点中单位,开始框选或移动指令
// 存储点击位置,用于判断是否是拖动操作
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.selectionStart = { x: worldX, y: worldY };
// 发送选择开始事件
this.scene.events.emit('selection-start', this.selectionStart);
// 没有点中单位,清除dragStart
this.dragStart = null;
}
} else if (pointer.rightButtonDown()) {
// 如果是右键按下,发送移动到指定点的事件
} else if (pointer.rightButtonDown() && this.enabledModes.mouse) {
// 如果是右键按下且鼠标模式启用,发送移动到指定点的事件
const worldX = pointer.worldX;
const worldY = pointer.worldY;
this.scene.events.emit('move-to-point', worldX, worldY);
// 右键点击,清除dragStart
this.dragStart = null;
}
}
// 处理鼠标/触摸移动事件
// @param {Object} pointer - 指针事件对象
onPointerMove(pointer) {
// 检查鼠标是否在小地图或摇杆上,如果是则不处理框选
if (this.isMouseOnMiniMap(pointer) || this.isMouseOnJoystick(pointer)) {
// 检查鼠标是否在小地图、摇杆或侧边栏上,如果是则不处理
if (this.isMouseOnMiniMap(pointer) || this.isMouseOnJoystick(pointer) || this.isMouseOnSidebar(pointer)) {
return;
}
// 如果当前正在进行框选操作
if (this.selectionStart) {
// 如果当前正在进行框选操作且框选功能启用
if (this.selectionStart && this.enabledModes.selection) {
// 获取当前鼠标在游戏世界中的坐标
const currentWorldX = pointer.worldX;
const currentWorldY = pointer.worldY;
@@ -143,23 +181,48 @@ export class InputSystem {
Math.abs(currentWorldY - this.selectionStart.y)
);
// 发送选择更新事件,更新框选区域的显示
this.scene.events.emit('selection-update', rect);
// 只有当框选区域足够大时才发送选择更新事件
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) {
// 检查鼠标是否在小地图或摇杆上,如果是则不处理框选
if (this.isMouseOnMiniMap(pointer) || this.isMouseOnJoystick(pointer)) {
// 重置框选起始点
// 检查鼠标是否在小地图、摇杆或侧边栏上,如果是则不处理
if (this.isMouseOnMiniMap(pointer) || this.isMouseOnJoystick(pointer) || this.isMouseOnSidebar(pointer)) {
// 重置框选起始点和拖动状态
this.selectionStart = null;
this.dragStart = null;
return;
}
// 如果当前正在进行框选操作
if (this.selectionStart) {
// 处理拖动单位的逻辑
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.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;
@@ -173,8 +236,8 @@ export class InputSystem {
);
// 如果框选区域太小(宽度和高度都小于10像素),视为点击地面移动
if (rect.width < 10 && rect.height < 10) {
// 发送移动到指定点的事件
if (rect.width < 10 && rect.height < 10 && this.enabledModes.mouse) {
// 发送移动到指定点的事件(仅在鼠标模式启用时)
this.scene.events.emit('move-to-point', pointer.worldX, pointer.worldY);
} else {
// 否则执行框选操作
@@ -203,11 +266,12 @@ export class InputSystem {
const mouseX = pointer.x;
const mouseY = pointer.y;
// 计算小地图的边界
// 计算小地图的边界(包括锁定按钮区域)
const mapLeft = miniMap.x; // 小地图左边界
const mapRight = miniMap.x + miniMap.mapSize; // 小地图右边界
const mapTop = miniMap.y; // 小地图上边界
const mapBottom = miniMap.y + miniMap.mapSize; // 小地图下边界
// 小地图下边界,包括锁定按钮(按钮高度25,边距5)
const mapBottom = miniMap.y + miniMap.mapSize + 30;
// 检查鼠标坐标是否在小地图边界内
return mouseX >= mapLeft && mouseX <= mapRight &&
@@ -242,4 +306,47 @@ export class InputSystem {
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;
}
}