From d48e9fa27bdf53da13a856baf0f87da348ba2f53 Mon Sep 17 00:00:00 2001 From: gronod Date: Mon, 2 Feb 2026 17:07:43 +0000 Subject: [PATCH] enhanced Chrome Android compatibility - improved touch events and audio --- pacman.html | 196 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 135 insertions(+), 61 deletions(-) diff --git a/pacman.html b/pacman.html index b20d22f..a62bb5e 100644 --- a/pacman.html +++ b/pacman.html @@ -87,10 +87,16 @@ const gameStateStatusElement = document.getElementById('gameStateStatus'); const controlsStatusElement = document.getElementById('controlsStatus'); - // Mobile detection + // Mobile detection - more comprehensive for Chrome Android const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) || (window.innerWidth <= 768 && 'ontouchstart' in window); + // Chrome Android specific detection + const isChromeAndroid = /Chrome/.test(navigator.userAgent) && /Android/.test(navigator.userAgent); + console.log('Mobile detected:', isMobile); + console.log('Chrome Android detected:', isChromeAndroid); + console.log('User agent:', navigator.userAgent); + // Update debug info function updateDebugInfo() { if (isMobileStatusElement) isMobileStatusElement.textContent = isMobile ? 'Yes' : 'No'; @@ -181,20 +187,35 @@ mouthAngle: 0.2 }; - // Sound system based on assembly audio routines + // Sound system based on assembly audio routines - enhanced for Chrome Android class SoundSystem { constructor() { this.audioContext = null; this.sounds = {}; + this.initialized = false; this.initAudio(); } initAudio() { try { - this.audioContext = new (window.AudioContext || window.webkitAudioContext)(); - this.createSounds(); + // Create audio context on first user interaction for Chrome Android + if (typeof AudioContext !== 'undefined' || typeof webkitAudioContext !== 'undefined') { + const AudioContextClass = window.AudioContext || window.webkitAudioContext; + this.audioContext = new AudioContextClass(); + + // Resume audio context if suspended (Chrome Android requirement) + if (this.audioContext.state === 'suspended') { + this.audioContext.resume(); + } + + this.createSounds(); + this.initialized = true; + console.log('Audio system initialized for Chrome Android'); + } else { + console.log('Web Audio API not supported'); + } } catch (e) { - console.log('Audio not supported'); + console.log('Audio initialization failed:', e); } } @@ -209,22 +230,31 @@ } playTone(frequency, duration) { - if (!this.audioContext) return; + if (!this.audioContext || !this.initialized) return; - const oscillator = this.audioContext.createOscillator(); - const gainNode = this.audioContext.createGain(); - - oscillator.connect(gainNode); - gainNode.connect(this.audioContext.destination); - - oscillator.frequency.value = frequency; - oscillator.type = 'square'; - - gainNode.gain.setValueAtTime(0.1, this.audioContext.currentTime); - gainNode.gain.exponentialRampToValueAtTime(0.01, this.audioContext.currentTime + duration / 1000); - - oscillator.start(this.audioContext.currentTime); - oscillator.stop(this.audioContext.currentTime + duration / 1000); + try { + // Resume audio context if suspended (Chrome Android) + if (this.audioContext.state === 'suspended') { + this.audioContext.resume(); + } + + const oscillator = this.audioContext.createOscillator(); + const gainNode = this.audioContext.createGain(); + + oscillator.connect(gainNode); + gainNode.connect(this.audioContext.destination); + + oscillator.frequency.value = frequency; + oscillator.type = 'square'; + + gainNode.gain.setValueAtTime(0.1, this.audioContext.currentTime); + gainNode.gain.exponentialRampToValueAtTime(0.01, this.audioContext.currentTime + duration / 1000); + + oscillator.start(this.audioContext.currentTime); + oscillator.stop(this.audioContext.currentTime + duration / 1000); + } catch (e) { + console.log('Error playing tone:', e); + } } play(soundName) { @@ -765,9 +795,9 @@ } }); - // Mobile touch controls + // Mobile touch controls - enhanced for Chrome Android function setupMobileControls() { - console.log('Setting up mobile controls...'); + console.log('Setting up mobile controls for Chrome Android...'); const dpadButtons = document.querySelectorAll('.dpad-btn'); dpadButtons.forEach(button => { @@ -776,10 +806,15 @@ console.log('Setting up button for direction:', direction); - // Touch start + // Enhanced touch events for Chrome Android button.addEventListener('touchstart', (e) => { e.preventDefault(); + e.stopPropagation(); console.log('Touch start for direction:', direction, 'Game state:', gameState); + + // Add visual feedback + button.style.backgroundColor = 'rgba(255, 255, 0, 0.8)'; + if (gameState === 'PLAYING') { pacman.nextDirection = direction; console.log('Set pacman direction to:', direction); @@ -788,47 +823,65 @@ pacman.nextDirection = direction; console.log('Set pacman direction to:', direction, '(testing mode)'); } - }); + }, { passive: false }); - // Mouse down (for testing on desktop) + button.addEventListener('touchend', (e) => { + e.preventDefault(); + e.stopPropagation(); + // Remove visual feedback + button.style.backgroundColor = ''; + }, { passive: false }); + + // Mouse events for desktop testing button.addEventListener('mousedown', (e) => { e.preventDefault(); console.log('Mouse down for direction:', direction, 'Game state:', gameState); + button.style.backgroundColor = 'rgba(255, 255, 0, 0.8)'; + if (gameState === 'PLAYING') { pacman.nextDirection = direction; console.log('Set pacman direction to:', direction); } else { - // For testing, allow direction changes in any state pacman.nextDirection = direction; console.log('Set pacman direction to:', direction, '(testing mode)'); } }); - // Touch end - button.addEventListener('touchend', (e) => { - e.preventDefault(); - }); - - // Mouse up button.addEventListener('mouseup', (e) => { e.preventDefault(); + button.style.backgroundColor = ''; }); }); - // Mobile space button + // Enhanced space button for Chrome Android mobileSpaceBtnElement.addEventListener('touchstart', (e) => { e.preventDefault(); + e.stopPropagation(); console.log('Mobile space button touched'); + mobileSpaceBtnElement.style.backgroundColor = 'rgba(0, 255, 255, 0.8)'; handleSpaceButton(); - }); + }, { passive: false }); + mobileSpaceBtnElement.addEventListener('touchend', (e) => { + e.preventDefault(); + e.stopPropagation(); + mobileSpaceBtnElement.style.backgroundColor = ''; + }, { passive: false }); + + // Mouse events for testing mobileSpaceBtnElement.addEventListener('mousedown', (e) => { e.preventDefault(); console.log('Mobile space button clicked'); + mobileSpaceBtnElement.style.backgroundColor = 'rgba(0, 255, 255, 0.8)'; handleSpaceButton(); }); - console.log('Mobile controls setup complete'); + mobileSpaceBtnElement.addEventListener('mouseup', (e) => { + e.preventDefault(); + mobileSpaceBtnElement.style.backgroundColor = ''; + }); + + console.log('Mobile controls setup complete for Chrome Android'); } function handleSpaceButton() { @@ -851,21 +904,39 @@ } } - // Initialize mobile controls if needed - if (isMobile || window.innerWidth <= 768) { - setupMobileControls(); + // Initialize game for Chrome Android + function initializeGame() { + console.log('Initializing game for Chrome Android...'); + + // Force show mobile controls + mobileControlsElement.classList.add('active'); + mobileSpaceBtnElement.style.display = 'block'; + + // Show start screen + startScreenElement.style.display = 'block'; + + // Set initial game state + gameState = 'START'; + attractModeTimer = 0; + + // Update debug info + updateDebugInfo(); + + // Setup mobile controls + if (isMobile || window.innerWidth <= 768) { + setupMobileControls(); + } + + console.log('Game initialized successfully'); + console.log('Game state:', gameState); + console.log('Mobile controls visible:', mobileControlsElement.classList.contains('active')); + console.log('Start screen visible:', startScreenElement.style.display); + + // Start game loop + gameLoop(); + gameLoopStarted = true; } - // Force show mobile controls for testing - mobileControlsElement.classList.add('active'); - mobileSpaceBtnElement.style.display = 'block'; - updateDebugInfo(); - - console.log('Game initialized with mobile controls'); - console.log('Mobile detected:', isMobile); - console.log('Window width:', window.innerWidth); - console.log('Mobile controls visible:', mobileControlsElement.classList.contains('active')); - // Test function for mobile controls window.testMobileControls = function() { console.log('Testing mobile controls...'); @@ -878,21 +949,24 @@ handleSpaceButton(); }; - // Start with START state instead of ATTRACT for easier testing - gameState = 'START'; - attractModeTimer = 0; + let gameLoopStarted = false; - // Show start screen immediately - startScreenElement.style.display = 'block'; + // Initialize on page load with fallback for Chrome Android + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initializeGame); + } else { + // DOM already loaded + initializeGame(); + } - console.log('Game starting in START state'); - console.log('Start screen visible:', startScreenElement.style.display); - - // Test if JavaScript is working - alert('JavaScript is loaded! Click OK to continue.'); - - // Start game loop - gameLoop(); + // Additional fallback for Chrome Android + window.addEventListener('load', function() { + console.log('Page fully loaded'); + if (!gameLoopStarted) { + console.log('Fallback initialization'); + initializeGame(); + } + });