// ==================== УПРАВЛЕНИЕ 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); }); }