mirror of
http://junepve.top:3000/chicrobot/CINC.git
synced 2026-10-30 02:51:29 +08:00
188 lines
6.2 KiB
JavaScript
188 lines
6.2 KiB
JavaScript
// 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;
|
|
}
|
|
} |