feat: add mobile virtual touch controls

- document.js: add is_touch detection and virtual button CSS
- input.js: create virtual D-pad + action buttons + touch drag camera
- main.js: skip Pointer Lock on touch devices
This commit is contained in:
Mai
2026-07-04 08:23:39 +08:00
parent b8cfe6ec32
commit dfb738f406
4 changed files with 324 additions and 3 deletions
+69
View File
@@ -81,3 +81,72 @@ c.onmouseup = (ev) => {
keys[key_action + ev.button] = 0;
};
// ─── Mobile virtual controls ───
if (is_touch) {
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;
}
});
}