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);