From c11dbc208d12f88965eda9b1b6bb5553cffc6be0 Mon Sep 17 00:00:00 2001 From: Matteo Benedetto Date: Wed, 1 Jul 2026 15:17:47 +0200 Subject: [PATCH] Mobile: touch controls with visual feedback, landscape support, larger hit areas --- docs/index.html | 319 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 215 insertions(+), 104 deletions(-) diff --git a/docs/index.html b/docs/index.html index 7d3e14c..6c2d880 100644 --- a/docs/index.html +++ b/docs/index.html @@ -2,36 +2,41 @@ - + A Scream from the Dark — WebAssembly Game Boy @@ -173,19 +241,25 @@
-
- - - - + +
+ + +
+ +
-
- - + + +
+ +
-
- - + + +
+ +
@@ -226,37 +300,74 @@ console.error('Errore:', err); }); - // WasmBoy native: Z=A, X=B, Enter=Start, Space=Select - const bindButton = (id, keyDef) => { - const btn = document.getElementById(id); - const trigger = (type) => (e) => { - e.preventDefault(); - let ev; - try { - ev = new KeyboardEvent(type, { key: keyDef.key, code: keyDef.code, bubbles: true, cancelable: true }); - } catch (e) { - ev = document.createEvent('KeyboardEvent'); - ev.initKeyboardEvent(type, true, true, window, keyDef.key, 0, false, false, false, false); - } - document.dispatchEvent(ev); - }; - btn.addEventListener('touchstart', trigger('keydown'), { passive: false }); - btn.addEventListener('touchend', trigger('keyup'), { passive: false }); - btn.addEventListener('mousedown', trigger('keydown')); - btn.addEventListener('mouseup', trigger('keyup')); - btn.addEventListener('mouseleave', trigger('keyup')); + /* ============================================ + Universal button binder (data-key driven) + - Touch: synthetic keydown/keyup events + - Mouse: same + - Visual feedback: .pressed class + - Multi-touch: each button tracks its own state + ============================================ */ + const KEY_CODE = { + 'ArrowUp':'ArrowUp','ArrowDown':'ArrowDown','ArrowLeft':'ArrowLeft','ArrowRight':'ArrowRight', + 'z':'KeyZ','Z':'KeyZ', + 'x':'KeyX','X':'KeyX', + 'Enter':'Enter','enter':'Enter', + ' ':'Space' + }; + const KEY_KEY = { + 'ArrowUp':'ArrowUp','ArrowDown':'ArrowDown','ArrowLeft':'ArrowLeft','ArrowRight':'ArrowRight', + 'z':'z','Z':'z', + 'x':'x','X':'x', + 'Enter':'Enter','enter':'Enter', + ' ':' ' }; - bindButton('btn-up', { key: 'ArrowUp', code: 'ArrowUp' }); - bindButton('btn-down', { key: 'ArrowDown', code: 'ArrowDown' }); - bindButton('btn-left', { key: 'ArrowLeft', code: 'ArrowLeft' }); - bindButton('btn-right', { key: 'ArrowRight', code: 'ArrowRight' }); - bindButton('btn-a', { key: 'z', code: 'KeyZ' }); - bindButton('btn-b', { key: 'x', code: 'KeyX' }); - bindButton('btn-start', { key: 'Enter', code: 'Enter' }); - bindButton('btn-select',{ key: ' ', code: 'Space' }); + function dispatchKey(type, dataKey) { + const ev = new KeyboardEvent(type, { + key: KEY_KEY[dataKey] || dataKey, + code: KEY_CODE[dataKey] || dataKey, + bubbles: true, + cancelable: true, + composed: true + }); + document.dispatchEvent(ev); + } - // Fullscreen toggle + document.querySelectorAll('.tbtn[data-key]').forEach(btn => { + const dataKey = btn.dataset.key; + let pressed = false; + const press = (e) => { + if (e) { e.preventDefault(); e.stopPropagation(); } + if (pressed) return; + pressed = true; + btn.classList.add('pressed'); + dispatchKey('keydown', dataKey); + }; + const release = (e) => { + if (e) { e.preventDefault(); e.stopPropagation(); } + if (!pressed) return; + pressed = false; + btn.classList.remove('pressed'); + dispatchKey('keyup', dataKey); + }; + // Touch (primary) + btn.addEventListener('touchstart', press, { passive: false }); + btn.addEventListener('touchend', release, { passive: false }); + btn.addEventListener('touchcancel',release, { passive: false }); + // Mouse (fallback per emulatori desktop e testing) + btn.addEventListener('mousedown', press); + btn.addEventListener('mouseup', release); + btn.addEventListener('mouseleave', release); + // Keyboard accessibility (Enter/Space su button = click = simulate tap) + btn.addEventListener('click', e => e.preventDefault()); // niente click reale + }); + + // Prevent default for arrow keys (avoid page scroll on Space/Arrows) + window.addEventListener('keydown', e => { + if (['ArrowUp','ArrowDown','ArrowLeft','ArrowRight',' '].includes(e.key)) e.preventDefault(); + }, { passive: false }); + + /* Fullscreen toggle */ const gameContainer = document.getElementById('game-container'); const fsButton = document.getElementById('btn-fullscreen'); fsButton.addEventListener('click', () => {