mirror of
http://junepve.top:3000/chicrobot/CINC.git
synced 2026-10-29 21:41:29 +08:00
111 lines
3.3 KiB
JavaScript
111 lines
3.3 KiB
JavaScript
// ui/VirtualJoystick.js
|
|
export class VirtualJoystick {
|
|
constructor(scene, enabled = true) {
|
|
this.scene = scene;
|
|
this.isActive = false;
|
|
this.base = null;
|
|
this.knob = null;
|
|
this.activePointer = null; // 保持单一激活指针,但允许不同指针触发
|
|
this.centerX = 0;
|
|
this.centerY = 0;
|
|
this.radius = 50;
|
|
this.enabled = enabled;
|
|
|
|
// 仅在启用时创建摇杆
|
|
if (this.enabled) {
|
|
// 在所有设备上都显示摇杆
|
|
this.create();
|
|
this.bindEvents();
|
|
}
|
|
}
|
|
|
|
create() {
|
|
const x = 200;
|
|
const y = this.scene.scale.height - 200;
|
|
this.centerX = x;
|
|
this.centerY = y;
|
|
|
|
this.base = this.scene.add.circle(x, y, this.radius, 0x444444, 0.5);
|
|
this.knob = this.scene.add.circle(x, y, this.radius * 0.5, 0xff0000, 0.8);
|
|
|
|
this.base.setScrollFactor(0); // 不随相机移动
|
|
this.knob.setScrollFactor(0);
|
|
}
|
|
|
|
bindEvents() {
|
|
this.scene.input.on('pointerdown', (ptr) => {
|
|
if (this.isInBase(ptr)) {
|
|
// 只有在没有激活指针时才设置新指针
|
|
// 这样可以避免不同触摸点之间的干扰
|
|
if (!this.isActive) {
|
|
this.activePointer = ptr;
|
|
this.isActive = true;
|
|
}
|
|
}
|
|
});
|
|
|
|
this.scene.input.on('pointermove', (ptr) => {
|
|
if (this.isActive && this.activePointer === ptr) {
|
|
const dx = ptr.x - this.centerX;
|
|
const dy = ptr.y - this.centerY;
|
|
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
|
|
if (distance > this.radius) {
|
|
// 限制在圆内
|
|
const angle = Math.atan2(dy, dx);
|
|
const knobX = this.centerX + Math.cos(angle) * this.radius;
|
|
const knobY = this.centerY + Math.sin(angle) * this.radius;
|
|
this.knob.setPosition(knobX, knobY);
|
|
} else {
|
|
this.knob.setPosition(ptr.x, ptr.y);
|
|
}
|
|
|
|
// 发送相对方向(归一化)
|
|
const dirX = dx / this.radius;
|
|
const dirY = dy / this.radius;
|
|
this.scene.events.emit('move-relative', { x: dirX, y: dirY });
|
|
}
|
|
});
|
|
|
|
this.scene.input.on('pointerup', (ptr) => {
|
|
if (this.activePointer === ptr) {
|
|
this.isActive = false;
|
|
this.activePointer = null;
|
|
this.knob.setPosition(this.centerX, this.centerY);
|
|
this.scene.events.emit('move-relative', { x: 0, y: 0 }); // 停止
|
|
}
|
|
});
|
|
|
|
// 处理指针离开屏幕的情况
|
|
this.scene.input.on('pointerout', (ptr) => {
|
|
if (this.activePointer === ptr) {
|
|
this.isActive = false;
|
|
this.activePointer = null;
|
|
this.knob.setPosition(this.centerX, this.centerY);
|
|
this.scene.events.emit('move-relative', { x: 0, y: 0 }); // 停止
|
|
}
|
|
});
|
|
}
|
|
|
|
isInBase(pointer) {
|
|
const dx = pointer.x - this.centerX;
|
|
const dy = pointer.y - this.centerY;
|
|
return Math.sqrt(dx * dx + dy * dy) <= this.radius + 20; // 容差
|
|
}
|
|
|
|
/**
|
|
* 更新方法,用于在游戏循环中持续发送移动指令
|
|
*/
|
|
update() {
|
|
// 仅在启用时更新
|
|
if (this.enabled && this.isActive && this.activePointer) {
|
|
const dx = this.activePointer.x - this.centerX;
|
|
const dy = this.activePointer.y - this.centerY;
|
|
|
|
// 发送相对方向(归一化)
|
|
const dirX = dx / this.radius;
|
|
const dirY = dy / this.radius;
|
|
this.scene.events.emit('move-relative', { x: dirX, y: dirY });
|
|
}
|
|
}
|
|
} |