3376c3e333
- Delay virtual controls creation until after game starts (ctrl overlay was intercepting title screen touches) - Add touchstart handler on game container for mobile entry - Add fullscreen button overlay in top-right corner - Hide title text after game starts
154 lines
4.2 KiB
JavaScript
Executable File
154 lines
4.2 KiB
JavaScript
Executable File
|
|
// 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
|
|
S: 3, o: 3, // Key[S] or ArrowD[o]wn
|
|
D: 4, i: 4, // Key[D] or ArrowR[i]ght
|
|
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;
|
|
};
|
|
|
|
// ─── Mobile virtual controls ───
|
|
|
|
// Called from main.js after game start
|
|
create_touch_controls = () => {
|
|
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;
|
|
}
|
|
});
|
|
};
|
|
|