enhanced Chrome Android compatibility - improved touch events and audio
This commit is contained in:
196
pacman.html
196
pacman.html
@@ -87,10 +87,16 @@
|
|||||||
const gameStateStatusElement = document.getElementById('gameStateStatus');
|
const gameStateStatusElement = document.getElementById('gameStateStatus');
|
||||||
const controlsStatusElement = document.getElementById('controlsStatus');
|
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) ||
|
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ||
|
||||||
(window.innerWidth <= 768 && 'ontouchstart' in window);
|
(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
|
// Update debug info
|
||||||
function updateDebugInfo() {
|
function updateDebugInfo() {
|
||||||
if (isMobileStatusElement) isMobileStatusElement.textContent = isMobile ? 'Yes' : 'No';
|
if (isMobileStatusElement) isMobileStatusElement.textContent = isMobile ? 'Yes' : 'No';
|
||||||
@@ -181,20 +187,35 @@
|
|||||||
mouthAngle: 0.2
|
mouthAngle: 0.2
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sound system based on assembly audio routines
|
// Sound system based on assembly audio routines - enhanced for Chrome Android
|
||||||
class SoundSystem {
|
class SoundSystem {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.audioContext = null;
|
this.audioContext = null;
|
||||||
this.sounds = {};
|
this.sounds = {};
|
||||||
|
this.initialized = false;
|
||||||
this.initAudio();
|
this.initAudio();
|
||||||
}
|
}
|
||||||
|
|
||||||
initAudio() {
|
initAudio() {
|
||||||
try {
|
try {
|
||||||
this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
// Create audio context on first user interaction for Chrome Android
|
||||||
this.createSounds();
|
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) {
|
} catch (e) {
|
||||||
console.log('Audio not supported');
|
console.log('Audio initialization failed:', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,22 +230,31 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
playTone(frequency, duration) {
|
playTone(frequency, duration) {
|
||||||
if (!this.audioContext) return;
|
if (!this.audioContext || !this.initialized) return;
|
||||||
|
|
||||||
const oscillator = this.audioContext.createOscillator();
|
try {
|
||||||
const gainNode = this.audioContext.createGain();
|
// Resume audio context if suspended (Chrome Android)
|
||||||
|
if (this.audioContext.state === 'suspended') {
|
||||||
oscillator.connect(gainNode);
|
this.audioContext.resume();
|
||||||
gainNode.connect(this.audioContext.destination);
|
}
|
||||||
|
|
||||||
oscillator.frequency.value = frequency;
|
const oscillator = this.audioContext.createOscillator();
|
||||||
oscillator.type = 'square';
|
const gainNode = this.audioContext.createGain();
|
||||||
|
|
||||||
gainNode.gain.setValueAtTime(0.1, this.audioContext.currentTime);
|
oscillator.connect(gainNode);
|
||||||
gainNode.gain.exponentialRampToValueAtTime(0.01, this.audioContext.currentTime + duration / 1000);
|
gainNode.connect(this.audioContext.destination);
|
||||||
|
|
||||||
oscillator.start(this.audioContext.currentTime);
|
oscillator.frequency.value = frequency;
|
||||||
oscillator.stop(this.audioContext.currentTime + duration / 1000);
|
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) {
|
play(soundName) {
|
||||||
@@ -765,9 +795,9 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mobile touch controls
|
// Mobile touch controls - enhanced for Chrome Android
|
||||||
function setupMobileControls() {
|
function setupMobileControls() {
|
||||||
console.log('Setting up mobile controls...');
|
console.log('Setting up mobile controls for Chrome Android...');
|
||||||
const dpadButtons = document.querySelectorAll('.dpad-btn');
|
const dpadButtons = document.querySelectorAll('.dpad-btn');
|
||||||
|
|
||||||
dpadButtons.forEach(button => {
|
dpadButtons.forEach(button => {
|
||||||
@@ -776,10 +806,15 @@
|
|||||||
|
|
||||||
console.log('Setting up button for direction:', direction);
|
console.log('Setting up button for direction:', direction);
|
||||||
|
|
||||||
// Touch start
|
// Enhanced touch events for Chrome Android
|
||||||
button.addEventListener('touchstart', (e) => {
|
button.addEventListener('touchstart', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
console.log('Touch start for direction:', direction, 'Game state:', gameState);
|
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') {
|
if (gameState === 'PLAYING') {
|
||||||
pacman.nextDirection = direction;
|
pacman.nextDirection = direction;
|
||||||
console.log('Set pacman direction to:', direction);
|
console.log('Set pacman direction to:', direction);
|
||||||
@@ -788,47 +823,65 @@
|
|||||||
pacman.nextDirection = direction;
|
pacman.nextDirection = direction;
|
||||||
console.log('Set pacman direction to:', direction, '(testing mode)');
|
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) => {
|
button.addEventListener('mousedown', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
console.log('Mouse down for direction:', direction, 'Game state:', gameState);
|
console.log('Mouse down for direction:', direction, 'Game state:', gameState);
|
||||||
|
button.style.backgroundColor = 'rgba(255, 255, 0, 0.8)';
|
||||||
|
|
||||||
if (gameState === 'PLAYING') {
|
if (gameState === 'PLAYING') {
|
||||||
pacman.nextDirection = direction;
|
pacman.nextDirection = direction;
|
||||||
console.log('Set pacman direction to:', direction);
|
console.log('Set pacman direction to:', direction);
|
||||||
} else {
|
} else {
|
||||||
// For testing, allow direction changes in any state
|
|
||||||
pacman.nextDirection = direction;
|
pacman.nextDirection = direction;
|
||||||
console.log('Set pacman direction to:', direction, '(testing mode)');
|
console.log('Set pacman direction to:', direction, '(testing mode)');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Touch end
|
|
||||||
button.addEventListener('touchend', (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Mouse up
|
|
||||||
button.addEventListener('mouseup', (e) => {
|
button.addEventListener('mouseup', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
button.style.backgroundColor = '';
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mobile space button
|
// Enhanced space button for Chrome Android
|
||||||
mobileSpaceBtnElement.addEventListener('touchstart', (e) => {
|
mobileSpaceBtnElement.addEventListener('touchstart', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
console.log('Mobile space button touched');
|
console.log('Mobile space button touched');
|
||||||
|
mobileSpaceBtnElement.style.backgroundColor = 'rgba(0, 255, 255, 0.8)';
|
||||||
handleSpaceButton();
|
handleSpaceButton();
|
||||||
});
|
}, { passive: false });
|
||||||
|
|
||||||
|
mobileSpaceBtnElement.addEventListener('touchend', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
mobileSpaceBtnElement.style.backgroundColor = '';
|
||||||
|
}, { passive: false });
|
||||||
|
|
||||||
|
// Mouse events for testing
|
||||||
mobileSpaceBtnElement.addEventListener('mousedown', (e) => {
|
mobileSpaceBtnElement.addEventListener('mousedown', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
console.log('Mobile space button clicked');
|
console.log('Mobile space button clicked');
|
||||||
|
mobileSpaceBtnElement.style.backgroundColor = 'rgba(0, 255, 255, 0.8)';
|
||||||
handleSpaceButton();
|
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() {
|
function handleSpaceButton() {
|
||||||
@@ -851,21 +904,39 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize mobile controls if needed
|
// Initialize game for Chrome Android
|
||||||
if (isMobile || window.innerWidth <= 768) {
|
function initializeGame() {
|
||||||
setupMobileControls();
|
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
|
// Test function for mobile controls
|
||||||
window.testMobileControls = function() {
|
window.testMobileControls = function() {
|
||||||
console.log('Testing mobile controls...');
|
console.log('Testing mobile controls...');
|
||||||
@@ -878,21 +949,24 @@
|
|||||||
handleSpaceButton();
|
handleSpaceButton();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Start with START state instead of ATTRACT for easier testing
|
let gameLoopStarted = false;
|
||||||
gameState = 'START';
|
|
||||||
attractModeTimer = 0;
|
|
||||||
|
|
||||||
// Show start screen immediately
|
// Initialize on page load with fallback for Chrome Android
|
||||||
startScreenElement.style.display = 'block';
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', initializeGame);
|
||||||
|
} else {
|
||||||
|
// DOM already loaded
|
||||||
|
initializeGame();
|
||||||
|
}
|
||||||
|
|
||||||
console.log('Game starting in START state');
|
// Additional fallback for Chrome Android
|
||||||
console.log('Start screen visible:', startScreenElement.style.display);
|
window.addEventListener('load', function() {
|
||||||
|
console.log('Page fully loaded');
|
||||||
// Test if JavaScript is working
|
if (!gameLoopStarted) {
|
||||||
alert('JavaScript is loaded! Click OK to continue.');
|
console.log('Fallback initialization');
|
||||||
|
initializeGame();
|
||||||
// Start game loop
|
}
|
||||||
gameLoop();
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user