// systems/InputSystem.js import { clearSelection, setActiveUnit } from './ControlMode.js'; export class InputSystem { constructor(scene) { this.scene = scene; this.selectionStart = null; // 初始化键盘 const kb = scene.input.keyboard; this.keys = { up: [kb.addKey(Phaser.Input.Keyboard.KeyCodes.W), kb.addKey(Phaser.Input.Keyboard.KeyCodes.UP)], down: [kb.addKey(Phaser.Input.Keyboard.KeyCodes.S), kb.addKey(Phaser.Input.Keyboard.KeyCodes.DOWN)], left: [kb.addKey(Phaser.Input.Keyboard.KeyCodes.A), kb.addKey(Phaser.Input.Keyboard.KeyCodes.LEFT)], right: [kb.addKey(Phaser.Input.Keyboard.KeyCodes.D), kb.addKey(Phaser.Input.Keyboard.KeyCodes.RIGHT)] }; // 禁用浏览器右键菜单 scene.input.mouse.disableContextMenu(); // 鼠标/触摸事件 scene.input.on('pointerdown', this.onPointerDown, this); scene.input.on('pointermove', this.onPointerMove, this); scene.input.on('pointerup', this.onPointerUp, this); } isKeyDown(keyGroup) { return keyGroup.some(key => key.isDown); } update() { // 键盘相对移动(仅当有激活单位) const dir = { x: 0, y: 0 }; if (this.isKeyDown(this.keys.left)) dir.x -= 1; if (this.isKeyDown(this.keys.right)) dir.x += 1; if (this.isKeyDown(this.keys.up)) dir.y -= 1; if (this.isKeyDown(this.keys.down)) dir.y += 1; // 无论是否有按键按下,都发送移动事件 // 当dir.x和dir.y都为0时,单位会停止移动 this.scene.events.emit('move-relative', dir); } onPointerDown(pointer) { // 检查鼠标是否在小地图或摇杆上,如果是则不处理框选 if (this.isMouseOnMiniMap(pointer) || this.isMouseOnJoystick(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; } }); if (clickedUnit) { // 切换控制目标 this.scene.events.emit('select-unit', clickedUnit); } else { // 开始框选或移动指令 // 存储世界坐标用于框选 this.selectionStart = { x: worldX, y: worldY }; this.scene.events.emit('selection-start', this.selectionStart); } } else if (pointer.rightButtonDown()) { // 右键点击:移动选中的单位 const worldX = pointer.worldX; const worldY = pointer.worldY; this.scene.events.emit('move-to-point', worldX, worldY); } } onPointerMove(pointer) { // 检查鼠标是否在小地图或摇杆上,如果是则不处理框选 if (this.isMouseOnMiniMap(pointer) || this.isMouseOnJoystick(pointer)) { return; } if (this.selectionStart) { // 使用世界坐标计算框选区域 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) ); // 更新选择框的位置和大小 this.scene.events.emit('selection-update', rect); } } onPointerUp(pointer) { // 检查鼠标是否在小地图或摇杆上,如果是则不处理框选 if (this.isMouseOnMiniMap(pointer) || this.isMouseOnJoystick(pointer)) { this.selectionStart = null; return; } if (this.selectionStart) { // 使用世界坐标计算最终框选区域 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) ); // 如果框太小,视为“点击地面移动” if (rect.width < 10 && rect.height < 10) { 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} */ 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; const mapBottom = miniMap.y + miniMap.mapSize; // 检查鼠标是否在小地图边界内 return mouseX >= mapLeft && mouseX <= mapRight && mouseY >= mapTop && mouseY <= mapBottom; } /** * 检查鼠标是否在摇杆上 * @param {Phaser.Input.Pointer} pointer * @returns {boolean} */ 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; } }