From 01997290a66369c0bdb10e9f6b9085a93c9e55e1 Mon Sep 17 00:00:00 2001 From: verboomp Date: Tue, 21 Apr 2026 15:45:14 +0200 Subject: [PATCH] pong mobile --- thiola-pong/game.js | 61 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/thiola-pong/game.js b/thiola-pong/game.js index cddb6ac..14118d4 100644 --- a/thiola-pong/game.js +++ b/thiola-pong/game.js @@ -252,6 +252,47 @@ mouseY = (e.clientY - rect.top) * (H / rect.height); }); + // Each touch is tracked by identifier so two fingers work independently (PvP tablet). + // Side is decided at touchstart: in PvP left half → player 1, right half → player 2. + // In CPU mode every touch controls player 1. + const activeTouches = new Map(); + + function getTouchSide(clientX) { + return (gameMode !== 'pvp' || clientX < window.innerWidth / 2) ? 'left' : 'right'; + } + + document.addEventListener('touchstart', e => { + // No preventDefault here — keeps tap→click working for buttons/popups/flash + if (!running) return; + for (const t of e.changedTouches) { + activeTouches.set(t.identifier, { side: getTouchSide(t.clientX), prevClientY: t.clientY }); + } + }, { passive: false }); + + document.addEventListener('touchmove', e => { + if (!running) return; + e.preventDefault(); // Prevent page scroll while dragging during gameplay + const scaleY = H / canvas.getBoundingClientRect().height; + for (const t of e.changedTouches) { + const touch = activeTouches.get(t.identifier); + if (!touch) continue; + const dy = (t.clientY - touch.prevClientY) * scaleY; + if (touch.side === 'left') playerY = Math.max(0, Math.min(H - PADDLE_H, playerY + dy)); + else cpuY = Math.max(0, Math.min(H - PADDLE_H, cpuY + dy)); + touch.prevClientY = t.clientY; + } + }, { passive: false }); + + document.addEventListener('touchend', e => { + for (const t of e.changedTouches) activeTouches.delete(t.identifier); + if (activeTouches.size === 0) mouseY = null; + }); + + document.addEventListener('touchcancel', e => { + for (const t of e.changedTouches) activeTouches.delete(t.identifier); + if (activeTouches.size === 0) mouseY = null; + }); + // ─── Update ─── function update() { if (!running || paused) return; @@ -260,13 +301,14 @@ const prevPlayerY = playerY; const prevCpuY = cpuY; - // Player 1 (left) — PvP: W/S only; CPU mode: mouse OR W/S - if (gameMode === 'pvp') { - if (keyW) playerY -= 6; - if (keyS) playerY += 6; - } else { + // Player 1 (left) — touch drag takes priority, then mouse, then keys + const leftTouched = [...activeTouches.values()].some(t => t.side === 'left'); + if (!leftTouched) { if (mouseY !== null) { playerY += (mouseY - PADDLE_H/2 - playerY) * 0.15; + } else if (gameMode === 'pvp') { + if (keyW) playerY -= 6; + if (keyS) playerY += 6; } else { if (keyUp || keyW) playerY -= 6; if (keyDown || keyS) playerY += 6; @@ -274,10 +316,13 @@ } playerY = Math.max(0, Math.min(H - PADDLE_H, playerY)); - // Player 2 / CPU (right) + // Player 2 / CPU (right) — touch drag takes priority, then keys / CPU AI + const rightTouched = [...activeTouches.values()].some(t => t.side === 'right'); if (gameMode === 'pvp') { - if (keyUp) cpuY -= 6; - if (keyDown) cpuY += 6; + if (!rightTouched) { + if (keyUp) cpuY -= 6; + if (keyDown) cpuY += 6; + } } else { const diff = ballY - (cpuY + PADDLE_H/2); if (Math.abs(diff) > 10) cpuY += Math.sign(diff) * Math.min(cpuSpeed, Math.abs(diff) * 0.07);