// game.js const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; let player = { x: 50, y: canvas.height - 150, width: 50, height: 50, color: 'blue', dy: 0 }; let coins = []; let morseCodeMessages = []; let gravity = 4.0; // Default gravity value let coinSpeed = 1.0; // Default coin speed let score = 0; let gameOver = false; let startTime = Date.now(); const gameDuration = 90 * 1000; // 1 minute 30 seconds in milliseconds const sensitivitySlider = document.getElementById('sensitivity'); const sensitivityValue = document.getElementById('sensitivityValue'); let micSensitivity = parseFloat(sensitivitySlider.value); const gravitySlider = document.getElementById('gravity'); const gravityValue = document.getElementById('gravityValue'); const coinSpeedSlider = document.getElementById('coinSpeed'); const coinSpeedValue = document.getElementById('coinSpeedValue'); // const forestWords = [""]; const forestWords = ['kanin']; const morseCodeMap = { 'a': '.-', 'b': '-...', 'c': '-.-.', 'd': '-..', 'e': '.', 'f': '..-.', 'g': '--.', 'h': '....', 'i': '..', 'j': '.---', 'k': '-.-', 'l': '.-..', 'm': '--', 'n': '-.', 'o': '---', 'p': '.--.', 'q': '--.-', 'r': '.-.', 's': '...', 't': '-', 'u': '..-', 'v': '...-', 'w': '.--', 'x': '-..-', 'y': '-.--', 'z': '--..', '1': '.----', '2': '..---', '3': '...--', '4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..', '9': '----.', '0': '-----' }; sensitivitySlider.addEventListener('input', () => { micSensitivity = parseFloat(sensitivitySlider.value); sensitivityValue.textContent = micSensitivity.toFixed(2); }); gravitySlider.addEventListener('input', () => { gravity = parseFloat(gravitySlider.value); gravityValue.textContent = gravity.toFixed(1); }); coinSpeedSlider.addEventListener('input', () => { coinSpeed = parseFloat(coinSpeedSlider.value); coinSpeedValue.textContent = coinSpeed.toFixed(1); }); // Function to convert a word to Morse code function wordToMorse(word) { return word.split('').map(char => morseCodeMap[char.toLowerCase()] || '').join(' '); } // Setup microphone input navigator.mediaDevices.getUserMedia({ audio: true }) .then(stream => { const audioContext = new (window.AudioContext || window.webkitAudioContext)(); const microphone = audioContext.createMediaStreamSource(stream); const analyser = audioContext.createAnalyser(); microphone.connect(analyser); analyser.fftSize = 256; const bufferLength = analyser.frequencyBinCount; const dataArray = new Uint8Array(bufferLength); function getMicrophoneInput() { analyser.getByteFrequencyData(dataArray); let values = 0; for (let i = 0; i < bufferLength; i++) { values += dataArray[i]; } return values / bufferLength; } function updatePlayer() { const micInput = getMicrophoneInput(); player.dy = -micInput * micSensitivity; player.dy += gravity; player.y += player.dy; if (player.y + player.height > canvas.height) { player.y = canvas.height - player.height; player.dy = 0; } else if (player.y < 0) { player.y = 0; player.dy = 0; } drawMicGauge(micInput); } function spawnCoin() { const coin = { x: canvas.width, y: Math.random() * (canvas.height - 50), radius: 15, color: 'gold', dx: -coinSpeed }; coins.push(coin); } function spawnMorseCodeMessage() { const word = forestWords[Math.floor(Math.random() * forestWords.length)]; const morseCode = wordToMorse(word); const message = { text: morseCode, x: canvas.width, y: Math.random() * (canvas.height - 50), dx: -1 }; morseCodeMessages.push(message); } function updateCoins() { for (let i = coins.length - 1; i >= 0; i--) { coins[i].x += coins[i].dx; if (coins[i].x + coins[i].radius < 0) { coins.splice(i, 1); } if ( player.x < coins[i].x + coins[i].radius && player.x + player.width > coins[i].x - coins[i].radius && player.y < coins[i].y + coins[i].radius && player.y + player.height > coins[i].y - coins[i].radius ) { score++; coins.splice(i, 1); } } } function updateMorseCodeMessages() { for (let i = morseCodeMessages.length - 1; i >= 0; i--) { morseCodeMessages[i].x += morseCodeMessages[i].dx; if (morseCodeMessages[i].x + ctx.measureText(morseCodeMessages[i].text).width < 0) { morseCodeMessages.splice(i, 1); } } } function drawPlayer() { ctx.fillStyle = player.color; ctx.fillRect(player.x, player.y, player.width, player.height); } function drawCoins() { for (let coin of coins) { ctx.beginPath(); ctx.arc(coin.x, coin.y, coin.radius, 0, Math.PI * 2, false); ctx.fillStyle = coin.color; ctx.fill(); ctx.closePath(); ctx.fillStyle = 'black'; ctx.font = '12px Arial'; ctx.fillText('1', coin.x - 3, coin.y + 4); } } function drawMorseCodeMessages() { ctx.fillStyle = 'lightgray'; ctx.font = '23px Arial'; for (let message of morseCodeMessages) { ctx.fillText(message.text, message.x, message.y); } } function drawScore() { ctx.fillStyle = 'rgba(128, 128, 128, 0.5)'; ctx.font = '100px Arial'; ctx.fillText('Score: ' + score, canvas.width / 2 - 200, canvas.height / 2); } function drawMicGauge(micInput) { const gaugeHeight = 10; const gaugeWidth = micInput * 2; ctx.fillStyle = 'green'; ctx.fillRect(10, 50, gaugeWidth, gaugeHeight); } function drawTimer(remainingTime) { ctx.fillStyle = 'black'; ctx.font = '20px Arial'; const minutes = Math.floor(remainingTime / 60000); const seconds = ((remainingTime % 60000) / 1000).toFixed(0); ctx.fillText(`Time: ${minutes}:${seconds < 10 ? '0' : ''}${seconds}`, 10, 280); } let coinInterval; let morseCodeInterval; let isGameLoopRunning = false; function resetGame() { player = { x: 50, y: canvas.height - 150, width: 50, height: 50, color: 'blue', dy: 0 }; coins = []; morseCodeMessages = []; score = 0; gameOver = false; startTime = Date.now(); // Clear the canvas ctx.clearRect(0, 0, canvas.width, canvas.height); // Hide the restart button restartButton.style.display = 'none'; // Clear existing intervals clearInterval(coinInterval); clearInterval(morseCodeInterval); // Start the game with coins and Morse code messages appearing immediately for (let i = 0; i < 5; i++) { spawnCoin(); spawnMorseCodeMessage(); } // Set new intervals coinInterval = setInterval(spawnCoin, 2000); morseCodeInterval = setInterval(spawnMorseCodeMessage, 3000); // Restart the game loop if not already running if (!isGameLoopRunning) { isGameLoopRunning = true; gameLoop(); } } const restartButton = document.getElementById('restartButton'); restartButton.addEventListener('click', () => { resetGame(); // restartButton.style.display = 'none'; }); const controls = document.getElementById('controls'); let controlsVisible = true; // Add this event listener to handle the 'R' key press document.addEventListener('keydown', (event) => { if (event.key === 'g' || event.key === 'G') { resetGame(); } if (event.key === 'c' || event.key === 'C') { controlsVisible = !controlsVisible; controls.style.display = controlsVisible ? 'block' : 'none'; } }); function gameLoop() { ctx.clearRect(0, 0, canvas.width, canvas.height); const currentTime = Date.now(); const elapsedTime = currentTime - startTime; const remainingTime = gameDuration - elapsedTime; if (remainingTime <= 0) { gameOver = true; } else { updatePlayer(); updateCoins(); updateMorseCodeMessages(); drawPlayer(); drawCoins(); drawMorseCodeMessages(); drawScore(); drawTimer(remainingTime); } if (gameOver) { ctx.fillStyle = 'rgba(0, 0, 0, 0.5)'; ctx.font = '50px Arial'; ctx.fillText('Game Over', canvas.width / 2 - 150, canvas.height / 2); ctx.fillText(`Final Score: ${score}`, canvas.width / 2 - 170, canvas.height / 2 + 60); restartButton.style.display = 'block'; isGameLoopRunning = false; } else { requestAnimationFrame(gameLoop); } } // Start the game with coins and Morse code messages appearing immediately for (let i = 0; i < 5; i++) { spawnCoin(); spawnMorseCodeMessage(); } setInterval(spawnCoin, 2000); setInterval(spawnMorseCodeMessage, 3000); gameLoop(); }) .catch(err => { console.error('Error accessing microphone:', err); });