mirror of
http://junepve.top:3000/chicrobot/CINC.git
synced 2026-10-29 22:41:29 +08:00
feat(control) 多角色控制
This commit is contained in:
1 parent
be5ee91328
commit
f86e5f3a79
11 files changed
+431
No files matched your search
@@ -0,0 +1,31 @@
|
||||
// systems/CommandSystem.js
|
||||
import { activeUnit, selectedUnits } from './ControlMode.js';
|
||||
|
||||
export class CommandSystem {
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
|
||||
scene.events.on('move-relative', this.onMoveRelative, this);
|
||||
scene.events.on('move-to-point', this.onMoveToPoint, this);
|
||||
scene.events.on('select-unit', this.onSelectUnit, this);
|
||||
}
|
||||
|
||||
onMoveRelative(dir) {
|
||||
if (activeUnit) {
|
||||
activeUnit.moveRelative(dir.x, dir.y);
|
||||
}
|
||||
}
|
||||
|
||||
onMoveToPoint(x, y) {
|
||||
const targets = selectedUnits.length > 0 ? selectedUnits : (activeUnit ? [activeUnit] : []);
|
||||
targets.forEach(unit => unit.moveTo(x, y));
|
||||
}
|
||||
|
||||
onSelectUnit(unit) {
|
||||
// 切换单位
|
||||
import('./ControlMode.js').then(mod => {
|
||||
mod.setActiveUnit(unit);
|
||||
this.scene.events.emit('unit-activated', unit);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
export const CONTROL_MODE = {
|
||||
SINGLE: 'single',
|
||||
GROUP: 'group',
|
||||
JOYSTICK: 'joystick'
|
||||
};
|
||||
|
||||
export let activeUnit = null;
|
||||
export let selectedUnits = [];
|
||||
|
||||
export function setActiveUnit(unit) {
|
||||
activeUnit = unit;
|
||||
selectedUnits = unit ? [unit] : [];
|
||||
}
|
||||
|
||||
export function addToSelection(unit) {
|
||||
if (!selectedUnits.includes(unit)) {
|
||||
selectedUnits.push(unit);
|
||||
}
|
||||
}
|
||||
|
||||
export function clearSelection() {
|
||||
activeUnit = null;
|
||||
selectedUnits = [];
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
// 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.on('pointerdown', this.onPointerDown, 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;
|
||||
|
||||
if (dir.x !== 0 || dir.y !== 0) {
|
||||
this.scene.events.emit('move-relative', dir);
|
||||
}
|
||||
}
|
||||
|
||||
onPointerDown(pointer) {
|
||||
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: pointer.x, y: pointer.y };
|
||||
this.scene.events.emit('selection-start', this.selectionStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onPointerUp(pointer) {
|
||||
if (this.selectionStart) {
|
||||
const rect = new Phaser.Geom.Rectangle(
|
||||
Math.min(this.selectionStart.x, pointer.x),
|
||||
Math.min(this.selectionStart.y, pointer.y),
|
||||
Math.abs(pointer.x - this.selectionStart.x),
|
||||
Math.abs(pointer.y - 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// systems/SelectionSystem.js
|
||||
import { clearSelection, addToSelection, setActiveUnit } from './ControlMode.js';
|
||||
|
||||
export class SelectionSystem {
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
this.selectionBox = null;
|
||||
|
||||
scene.events.on('selection-start', this.onStart, this);
|
||||
scene.events.on('selection-end', this.onEnd, this);
|
||||
}
|
||||
|
||||
onStart(pos) {
|
||||
if (!this.selectionBox) {
|
||||
this.selectionBox = this.scene.add.rectangle(pos.x, pos.y, 1, 1, 0x00ff00, 0.3)
|
||||
.setStrokeStyle(1, 0xffffff)
|
||||
.setVisible(true);
|
||||
} else {
|
||||
this.selectionBox.setPosition(pos.x, pos.y).setSize(1, 1).setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
onEnd(rect) {
|
||||
if (this.selectionBox) {
|
||||
this.selectionBox.setVisible(false);
|
||||
}
|
||||
|
||||
const units = this.scene.unitGroup.getChildren();
|
||||
const selected = units.filter(unit => {
|
||||
const unitRect = unit.getBounds();
|
||||
return Phaser.Geom.Rectangle.Overlaps(rect, unitRect);
|
||||
});
|
||||
|
||||
clearSelection();
|
||||
selected.forEach(addToSelection);
|
||||
|
||||
if (selected.length > 0) {
|
||||
setActiveUnit(selected[0]); // 激活第一个
|
||||
this.scene.events.emit('units-selected', selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user