grechka-game/srcv3/input/controls3d.js

67 lines
2.5 KiB
JavaScript

// ==================== УПРАВЛЕНИЕ 3D — клавиатура + мышь ====================
// Клавиши работают напрямую через state.inp.fwd / state.inp.side (аналоговые оси -1..1),
// поэтому движение на компе идёт по той же схеме, что и джойстик на телефоне.
import { state } from '../core/state.js';
// клавиши, которые не должны скроллить страницу/открывать меню
const SWALLOW = new Set([
'Space', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight',
'KeyW', 'KeyA', 'KeyS', 'KeyD',
]);
// истина, если игрок сейчас печатает в поле ввода
function typing() {
const el = document.activeElement;
if (!el) return false;
const t = el.tagName;
return t === 'INPUT' || t === 'TEXTAREA' || el.isContentEditable;
}
function applyKey(code, down) {
const inp = state.inp;
switch (code) {
// движение вперёд/назад и влево/вправо — по камере
case 'KeyW': case 'ArrowUp': inp.kfwd = down ? -1 : 0; break;
case 'KeyS': case 'ArrowDown': inp.kfwd = down ? 1 : 0; break;
case 'KeyA': case 'ArrowLeft': inp.kside = down ? -1 : 0; break;
case 'KeyD': case 'ArrowRight': inp.kside = down ? 1 : 0; break;
// прыжок
case 'Space': case 'KeyZ': inp.j = down; break;
// спуск по лестнице / вниз
case 'ShiftLeft': case 'KeyC': inp.s = down; break;
default: return false;
}
return true;
}
export function initControls() {
window.addEventListener('keydown', (e) => {
if (typing()) return;
if (e.repeat) return;
if (SWALLOW.has(e.code)) e.preventDefault();
applyKey(e.code, true);
});
window.addEventListener('keyup', (e) => {
if (typing()) return;
applyKey(e.code, false);
});
// если окно потеряло фокус — сбрасываем всё, иначе персонаж «убегает» сам
window.addEventListener('blur', () => {
const inp = state.inp;
inp.kfwd = 0; inp.kside = 0; inp.j = false; inp.s = false;
});
// на всякий случай дублируем на document (фокус может быть на канвасе)
document.addEventListener('keydown', (e) => {
if (typing()) return;
if (e.repeat) return;
applyKey(e.code, true);
});
document.addEventListener('keyup', (e) => {
if (typing()) return;
applyKey(e.code, false);
});
}