Files
q1k3/source/input.js
T

154 lines
4.2 KiB
JavaScript
Raw Normal View History

2021-09-13 09:34:08 +02:00
// We use the ev.code for keyboard input. This contains a string like "KeyW"
// or "ArrowLeft", which is awkward to use, but it's keyboard layout neutral,
// so that WASD should work with any layout.
// We detect the 6th or 3rd char for each of those strings and map them to an
// in-game button.
// Movement, Action, Prev/Next, Jump
let keymap = {
W: 1, p: 1, // Key[W] or ArrowU[p]
A: 2, e: 2, // Key[A] or ArrowL[e]ft
2021-09-14 08:48:20 +02:00
S: 3, o: 3, // Key[S] or ArrowD[o]wn
D: 4, i: 4, // Key[D] or ArrowR[i]ght
2021-09-13 09:34:08 +02:00
Q: 5, // Key[Q]
E: 6, // Key[E]
c: 9, // KeySpa[c]e
},
keys = [
// Unused zeroth key, so we can test the keymap result for truthiness
0,
// WASD/Arrow Keys and prev next have to be set to zero, because we use
// the value (0 or 1) to calculate the move direction or weapon switch
0,0,0,0,
0,0
// Following Keys (action, jump) to not have to be set here
// as they are just tested for truthiness
],
key_up = 1,
key_down = 3,
key_left = 2,
key_right = 4,
key_prev = 5,
key_next = 6,
key_action = 7, // ev.button = 0
key_jump = 9, // ev.button = 2
mouse_x = 0,
mouse_y = 0,
last_wheel_event = 0;
document.onkeydown = (ev) => {
let k = keymap[ev.code[6] || ev.code[3]];
if (k) {
ev.preventDefault();
keys[k] = 1;
}
};
document.onkeyup = (ev) => {
let k = keymap[ev.code[6] || ev.code[3]];
if (k) {
ev.preventDefault();
keys[k] = 0;
}
};
document.onwheel = (ev) => {
// Allow for one wheel event every 0.1s. This sucks, but prevents free
// spinning or touch scrolling mouses (eg. Apple Magic Mouse) from doing
// wild things.
if (game_time - last_wheel_event > 0.1) {
keys[key_prev + (ev.deltaY > 1 ? 1 : 0)] = 1;
last_wheel_event = game_time;
}
};
c.onmousemove = (ev) => {
mouse_x += ev.movementX;
mouse_y += ev.movementY;
};
c.onmousedown = (ev) => {
ev.preventDefault();
keys[key_action + ev.button] = 1;
};
c.onmouseup = (ev) => {
ev.preventDefault();
keys[key_action + ev.button] = 0;
};
2026-07-04 08:23:39 +08:00
// ─── Mobile virtual controls ───
// Called from main.js after game start
create_touch_controls = () => {
2026-07-04 08:23:39 +08:00
let ctrl = document.createElement('div');
ctrl.id = 'ctrl';
ctrl.innerHTML =
'<div id="ctrl-left">'+
'<button class="ctrl-btn" id="btn-up">▲</button>'+
'<button class="ctrl-btn" id="btn-left">◀</button>'+
'<button class="ctrl-btn" id="btn-right">▶</button>'+
'<button class="ctrl-btn" id="btn-down">▼</button>'+
'</div>'+
'<div id="ctrl-right"></div>'+
'<div id="ctrl-actions">'+
'<button class="ctrl-btn ctrl-shoot" id="btn-shoot">⚡</button>'+
'<button class="ctrl-btn ctrl-prev" id="btn-prev">◀◀</button>'+
'<button class="ctrl-btn ctrl-next" id="btn-next">▶▶</button>'+
'<button class="ctrl-btn ctrl-jump" id="btn-jump">▲</button>'+
'</div>';
document.getElementById('g').appendChild(ctrl);
// Prevent touches from reaching the canvas
ctrl.addEventListener('touchstart', (e) => e.preventDefault(), {passive: false});
ctrl.addEventListener('touchmove', (e) => e.preventDefault(), {passive: false});
// Bind button press/release
let bindBtn = (id, keyIndex) => {
let el = document.getElementById(id);
el.addEventListener('touchstart', () => { keys[keyIndex] = 1; });
el.addEventListener('touchend', () => { keys[keyIndex] = 0; });
el.addEventListener('touchcancel', () => { keys[keyIndex] = 0; });
};
bindBtn('btn-up', 1);
bindBtn('btn-down', 3);
bindBtn('btn-left', 2);
bindBtn('btn-right', 4);
bindBtn('btn-shoot', 7);
bindBtn('btn-jump', 9);
bindBtn('btn-prev', 5);
bindBtn('btn-next', 6);
// Right zone touch drag → camera
let rightZone = document.getElementById('ctrl-right'),
touch_id = null,
last_tx = 0,
last_ty = 0;
rightZone.addEventListener('touchstart', (e) => {
let t = e.changedTouches[0];
touch_id = t.identifier;
last_tx = t.clientX;
last_ty = t.clientY;
});
rightZone.addEventListener('touchmove', (e) => {
for (let t of e.changedTouches) {
if (t.identifier === touch_id) {
mouse_x += t.clientX - last_tx;
mouse_y += t.clientY - last_ty;
last_tx = t.clientX;
last_ty = t.clientY;
}
}
});
rightZone.addEventListener('touchend', (e) => {
for (let t of e.changedTouches) {
if (t.identifier === touch_id) touch_id = null;
}
});
};
2026-07-04 08:23:39 +08:00