enhanced Chrome Android compatibility - improved touch events and audio

This commit is contained in:
2026-02-02 17:07:43 +00:00
parent 0e20e6d030
commit d48e9fa27b

View File

@@ -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();
try {
// Resume audio context if suspended (Chrome Android)
if (this.audioContext.state === 'suspended') {
this.audioContext.resume();
}
oscillator.connect(gainNode);
gainNode.connect(this.audioContext.destination);
const oscillator = this.audioContext.createOscillator();
const gainNode = this.audioContext.createGain();
oscillator.frequency.value = frequency;
oscillator.type = 'square';
oscillator.connect(gainNode);
gainNode.connect(this.audioContext.destination);
gainNode.gain.setValueAtTime(0.1, this.audioContext.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.01, this.audioContext.currentTime + duration / 1000);
oscillator.frequency.value = frequency;
oscillator.type = 'square';
oscillator.start(this.audioContext.currentTime);
oscillator.stop(this.audioContext.currentTime + duration / 1000);
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();
}
});
</script>
</body>
</html>