148 lines
5.0 KiB
JavaScript
148 lines
5.0 KiB
JavaScript
import { Vector2D } from './Vector2D.js';
|
|
|
|
export class Input {
|
|
constructor(canvas, viewport) {
|
|
this.keys = new Set();
|
|
this.pressed = new Set();
|
|
this.mouse = new Vector2D(viewport.width / 2, viewport.height / 2);
|
|
this.mouseDown = false;
|
|
this.mouseClicked = false;
|
|
this.viewport = viewport;
|
|
this.isMobile = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
|
|
this.joystickActive = false;
|
|
this.joystickTouchId = null;
|
|
this.joystickBasePos = { x: 0, y: 0 };
|
|
this.joystickRadius = 60;
|
|
|
|
window.addEventListener('keydown', (event) => {
|
|
this.keys.add(event.key.toLowerCase());
|
|
if (!event.repeat) {
|
|
this.pressed.add(event.key.toLowerCase());
|
|
}
|
|
if (event.key === ' ') {
|
|
event.preventDefault();
|
|
if (
|
|
document.activeElement &&
|
|
document.activeElement.tagName === 'BUTTON' &&
|
|
typeof document.activeElement.blur === 'function'
|
|
) {
|
|
document.activeElement.blur();
|
|
}
|
|
}
|
|
});
|
|
window.addEventListener('keyup', (event) => {
|
|
this.keys.delete(event.key.toLowerCase());
|
|
});
|
|
window.addEventListener('blur', () => {
|
|
this.keys.clear();
|
|
this.pressed.clear();
|
|
this.mouseDown = false;
|
|
});
|
|
|
|
canvas.addEventListener('mousemove', (event) => {
|
|
const rect = canvas.getBoundingClientRect();
|
|
this.mouse.x = ((event.clientX - rect.left) / rect.width) * viewport.width;
|
|
this.mouse.y = ((event.clientY - rect.top) / rect.height) * viewport.height;
|
|
});
|
|
canvas.addEventListener('mousedown', (event) => {
|
|
if (event.button === 0) {
|
|
this.mouseDown = true;
|
|
this.mouseClicked = true;
|
|
}
|
|
});
|
|
window.addEventListener('mouseup', () => {
|
|
this.mouseDown = false;
|
|
});
|
|
|
|
if (this.isMobile) {
|
|
this._initTouchJoystick(canvas);
|
|
}
|
|
}
|
|
|
|
_initTouchJoystick(canvas) {
|
|
this.joystickBaseEl = document.createElement('div');
|
|
this.joystickBaseEl.className = 'joystick-base';
|
|
this.joystickBaseEl.style.display = 'none';
|
|
|
|
this.joystickThumbEl = document.createElement('div');
|
|
this.joystickThumbEl.className = 'joystick-thumb';
|
|
this.joystickThumbEl.style.display = 'none';
|
|
|
|
document.body.appendChild(this.joystickBaseEl);
|
|
document.body.appendChild(this.joystickThumbEl);
|
|
|
|
canvas.addEventListener('touchstart', (event) => this._handleTouchStart(event), { passive: false });
|
|
canvas.addEventListener('touchmove', (event) => this._handleTouchMove(event), { passive: false });
|
|
canvas.addEventListener('touchend', (event) => this._handleTouchEnd(event), { passive: false });
|
|
canvas.addEventListener('touchcancel', (event) => this._handleTouchEnd(event), { passive: false });
|
|
}
|
|
|
|
_handleTouchStart(event) {
|
|
event.preventDefault();
|
|
for (const touch of event.changedTouches) {
|
|
const x = touch.clientX;
|
|
if (x < this.viewport.width / 2 && !this.joystickActive) {
|
|
this.joystickActive = true;
|
|
this.joystickTouchId = touch.identifier;
|
|
this.joystickBasePos.x = x;
|
|
this.joystickBasePos.y = touch.clientY;
|
|
|
|
this.joystickBaseEl.style.left = `${x}px`;
|
|
this.joystickBaseEl.style.top = `${this.joystickBasePos.y}px`;
|
|
this.joystickBaseEl.style.display = 'block';
|
|
this.joystickThumbEl.style.left = `${x}px`;
|
|
this.joystickThumbEl.style.top = `${this.joystickBasePos.y}px`;
|
|
this.joystickThumbEl.style.display = 'block';
|
|
}
|
|
}
|
|
}
|
|
|
|
_handleTouchMove(event) {
|
|
event.preventDefault();
|
|
for (const touch of event.changedTouches) {
|
|
if (touch.identifier !== this.joystickTouchId) continue;
|
|
const dx = touch.clientX - this.joystickBasePos.x;
|
|
const dy = touch.clientY - this.joystickBasePos.y;
|
|
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
let clampedDx = dx;
|
|
let clampedDy = dy;
|
|
if (dist > this.joystickRadius) {
|
|
clampedDx = (dx / dist) * this.joystickRadius;
|
|
clampedDy = (dy / dist) * this.joystickRadius;
|
|
}
|
|
|
|
this.joystickThumbEl.style.left = `${this.joystickBasePos.x + clampedDx}px`;
|
|
this.joystickThumbEl.style.top = `${this.joystickBasePos.y + clampedDy}px`;
|
|
|
|
const deadZone = 12;
|
|
this.keys.delete('w');
|
|
this.keys.delete('a');
|
|
this.keys.delete('s');
|
|
this.keys.delete('d');
|
|
if (dy < -deadZone) this.keys.add('w');
|
|
if (dy > deadZone) this.keys.add('s');
|
|
if (dx < -deadZone) this.keys.add('a');
|
|
if (dx > deadZone) this.keys.add('d');
|
|
}
|
|
}
|
|
|
|
_handleTouchEnd(event) {
|
|
for (const touch of event.changedTouches) {
|
|
if (touch.identifier === this.joystickTouchId) {
|
|
this.joystickActive = false;
|
|
this.joystickTouchId = null;
|
|
this.keys.delete('w');
|
|
this.keys.delete('a');
|
|
this.keys.delete('s');
|
|
this.keys.delete('d');
|
|
this.joystickBaseEl.style.display = 'none';
|
|
this.joystickThumbEl.style.display = 'none';
|
|
}
|
|
}
|
|
}
|
|
|
|
clearPressed() {
|
|
this.pressed.clear();
|
|
this.mouseClicked = false;
|
|
}
|
|
} |