<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Изменение времени по голосу</title> <style> body { margin: 0; overflow: hidden; font-family: Arial, sans-serif; } #game-container { position: relative; width: 100vw; height: 100vh; transition: background-color 0.5s ease; } #sky { position: absolute; top: 0; left: 0; width: 100%; height: 70%; transition: background-color 0.5s ease; } #ground { position: absolute; bottom: 0; left: 0; width: 100%; height: 30%; background-color: #4a7c59; transition: background-color 0.5s ease; } #sun-moon { position: absolute; width: 80px; height: 80px; border-radius: 50%; transition: all 0.5s ease; } #buildings { position: absolute; bottom: 30%; left: 0; width: 100%; height: 20%; } .building { position: absolute; bottom: 0; background-color: #555; transition: background-color 0.5s ease; } .window { position: absolute; background-color: #333; transition: background-color 0.5s ease; } #controls { position: absolute; top: 20px; left: 20px; background-color: rgba(255, 255, 255, 0.8); padding: 15px; border-radius: 10px; z-index: 100; } #time-display { font-size: 24px; font-weight: bold; margin-bottom: 10px; } #pitch-display, #volume-display { font-size: 16px; margin-bottom: 5px; } button { padding: 10px 15px; margin-right: 5px; background-color: #4CAF50; color: white; border: none; border-radius: 5px; cursor: pointer; } button:hover { background-color: #45a049; } #stars { position: absolute; top: 0; left: 0; width: 100%; height: 70%; transition: opacity 0.5s ease; opacity: 0; } .star { position: absolute; background-color: white; border-radius: 50%; } #instructions { position: absolute; bottom: 20px; left: 20px; background-color: rgba(255, 255, 255, 0.8); padding: 15px; border-radius: 10px; max-width: 300px; } </style> </head> <body> <div id="game-container"> <div id="sky"></div> <div id="stars"></div> <div id="sun-moon"></div> <div id="buildings"></div> <div id="ground"></div> <div id="controls"> <div id="time-display">12:00</div> <div id="pitch-display">Тембр: 0</div> <div id="volume-display">Громкость: 0</div> <button id="start-btn">Начать запись голоса</button> <button id="stop-btn" disabled>Остановить</button> </div> <div id="instructions"> <h3>Инструкция:</h3> <p>1. Нажмите "Начать запись голоса" и разрешите доступ к микрофону</p> <p>2. Говорите с разным тембром голоса:</p> <p>- Низкий тембр = ночь/раннее утро</p> <p>- Средний тембр = день</p> <p>- Высокий тембр = вечер/закат</p> <p>3. Громкость голоса влияет на яркость сцены</p> </div> </div> <script> // Создаем элементы сцены function setupScene() { // Создаем здания const buildingsContainer = document.getElementById('buildings'); const buildingCount = 8; for (let i = 0; i < buildingCount; i++) { const building = document.createElement('div'); building.classList.add('building'); const height = 50 + Math.random() * 100; const width = 40 + Math.random() * 60; building.style.height = height + 'px'; building.style.width = width + 'px'; building.style.left = (i * (100 / buildingCount)) + '%'; // Добавляем окна const windowRows = Math.floor(height / 20); const windowCols = Math.floor(width / 15); for (let r = 0; r < windowRows; r++) { for (let c = 0; c < windowCols; c++) { const windowEl = document.createElement('div'); windowEl.classList.add('window'); windowEl.style.width = '10px'; windowEl.style.height = '15px'; windowEl.style.left = (c * 15 + 5) + 'px'; windowEl.style.top = (r * 20 + 5) + 'px'; building.appendChild(windowEl); } } buildingsContainer.appendChild(building); } // Создаем звезды const starsContainer = document.getElementById('stars'); for (let i = 0; i < 100; i++) { const star = document.createElement('div'); star.classList.add('star'); const size = 1 + Math.random() * 2; star.style.width = size + 'px'; star.style.height = size + 'px'; star.style.left = Math.random() * 100 + '%'; star.style.top = Math.random() * 100 + '%'; starsContainer.appendChild(star); } } // Изменение времени суток function updateTimeOfDay(hour, minute, pitch, volume) { const gameContainer = document.getElementById('game-container'); const sky = document.getElementById('sky'); const ground = document.getElementById('ground'); const sunMoon = document.getElementById('sun-moon'); const buildings = document.querySelectorAll('.building'); const windows = document.querySelectorAll('.window'); const stars = document.getElementById('stars'); // Нормализуем время (0-24) const time = hour + minute / 60; // Положение солнца/луны const angle = (time / 24) * 2 * Math.PI - Math.PI / 2; const radius = Math.min(window.innerWidth, window.innerHeight) * 0.4; const centerX = window.innerWidth / 2; const centerY = window.innerHeight * 0.7; const x = centerX + radius * Math.cos(angle); const y = centerY + radius * Math.sin(angle); sunMoon.style.left = (x - 40) + 'px'; sunMoon.style.top = (y - 40) + 'px'; // Цвета в зависимости от времени суток let skyColor, groundColor, sunMoonColor, buildingColor, windowColor; let starsOpacity = 0; // Раннее утро (5-7) if (time >= 5 && time < 7) { skyColor = `rgb(${Math.floor(59 + (158-59) * (time-5)/2)}, ${Math.floor(88 + (206-88) * (time-5)/2)}, ${Math.floor(128 + (235-128) * (time-5)/2)})`; groundColor = '#385c46'; sunMoonColor = '#ff9e4f'; buildingColor = '#555'; windowColor = '#333'; } // День (7-17) else if (time >= 7 && time < 17) { skyColor = '#9eceff'; groundColor = '#4a7c59'; sunMoonColor = '#ffee00'; buildingColor = '#666'; windowColor = '#444'; } // Закат (17-19) else if (time >= 17 && time < 19) { const factor = (time - 17) / 2; skyColor = `rgb(${Math.floor(158 + (255-158) * factor)}, ${Math.floor(206 + (107-206) * factor)}, ${Math.floor(235 + (62-235) * factor)})`; groundColor = '#3d5d49'; sunMoonColor = '#ff6700'; buildingColor = '#555'; windowColor = '#b3721f'; } // Вечер (19-21) else if (time >= 19 && time < 21) { const factor = (time - 19) / 2; skyColor = `rgb(${Math.floor(255 - (255-20) * factor)}, ${Math.floor(107 - (107-42) * factor)}, ${Math.floor(62 - (62-87) * factor)})`; groundColor = '#2e463a'; sunMoonColor = `rgb(${Math.floor(255 - 200 * factor)}, ${Math.floor(103 - 43 * factor)}, ${Math.floor(0 + 230 * factor)})`; buildingColor = '#444'; windowColor = '#ffdb70'; starsOpacity = factor; } // Ночь (21-5) else { skyColor = '#14283b'; groundColor = '#1e2e26'; sunMoonColor = '#e0e0e0'; buildingColor = '#333'; windowColor = '#ffdb70'; starsOpacity = 1; } // Применяем цвета с учетом громкости (яркости) const brightnessMultiplier = 0.7 + volume * 0.3; // Функция для увеличения яркости цвета function adjustBrightness(hexOrRgb, multiplier) { // Для RGB формата if (hexOrRgb.startsWith('rgb')) { const rgbValues = hexOrRgb.match(/\d+/g).map(Number); return `rgb(${Math.min(255, Math.floor(rgbValues[0] * multiplier))}, ${Math.min(255, Math.floor(rgbValues[1] * multiplier))}, ${Math.min(255, Math.floor(rgbValues[2] * multiplier))})`; } // Для HEX формата const hex = hexOrRgb.replace('#', ''); let r = parseInt(hex.substring(0, 2), 16); let g = parseInt(hex.substring(2, 4), 16); let b = parseInt(hex.substring(4, 6), 16); r = Math.min(255, Math.floor(r * multiplier)); g = Math.min(255, Math.floor(g * multiplier)); b = Math.min(255, Math.floor(b * multiplier)); return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`; } // Применяем подстроенные цвета sky.style.backgroundColor = skyColor; ground.style.backgroundColor = adjustBrightness(groundColor, brightnessMultiplier); sunMoon.style.backgroundColor = adjustBrightness(sunMoonColor, brightnessMultiplier); buildings.forEach(building => { building.style.backgroundColor = adjustBrightness(buildingColor, brightnessMultiplier); }); windows.forEach(window => { // Ночью окна горят if (time >= 19 || time < 7) { // Случайно определяем, горит ли окно if (window.dataset.lit === undefined) { window.dataset.lit = Math.random() > 0.3 ? 'true' : 'false'; } if (window.dataset.lit === 'true') { window.style.backgroundColor = adjustBrightness(windowColor, brightnessMultiplier); } else { window.style.backgroundColor = '#333'; } } else { // Днем окна темные window.style.backgroundColor = '#444'; delete window.dataset.lit; } }); stars.style.opacity = starsOpacity; } // Обработка аудио let audioContext; let analyser; let microphone; let javascriptNode; let hours = 12; let minutes = 0; let lastPitch = 0; let lastVolume = 0; function startAudioProcessing() { const startBtn = document.getElementById('start-btn'); const stopBtn = document.getElementById('stop-btn'); startBtn.disabled = true; stopBtn.disabled = false; audioContext = new (window.AudioContext || window.webkitAudioContext)(); analyser = audioContext.createAnalyser(); analyser.fftSize = 2048; // Запрашиваем доступ к микрофону navigator.mediaDevices.getUserMedia({ audio: true }) .then(function(stream) { microphone = audioContext.createMediaStreamSource(stream); microphone.connect(analyser); // Создаем обработчик для анализа звука javascriptNode = audioContext.createScriptProcessor(2048, 1, 1); analyser.connect(javascriptNode); javascriptNode.connect(audioContext.destination); // Устанавливаем обработчик для анализа звука javascriptNode.onaudioprocess = processAudio; }) .catch(function(err) { console.error('Ошибка доступа к микрофону:', err); alert('Не удалось получить доступ к микрофону. Проверьте настройки браузера.'); startBtn.disabled = false; stopBtn.disabled = true; }); } function stopAudioProcessing() { const startBtn = document.getElementById('start-btn'); const stopBtn = document.getElementById('stop-btn'); startBtn.disabled = false; stopBtn.disabled = true; if (javascriptNode) { javascriptNode.onaudioprocess = null; javascriptNode.disconnect(); } if (microphone) { microphone.disconnect(); } if (analyser) { analyser.disconnect(); } if (audioContext) { audioContext.close(); } } function processAudio(event) { const bufferLength = analyser.frequencyBinCount; const dataArray = new Uint8Array(bufferLength); analyser.getByteFrequencyData(dataArray); // Вычисляем среднюю частоту (тембр) let sum = 0; let count = 0; // Используем только значимую часть спектра for (let i = 5; i < bufferLength / 4; i++) { if (dataArray[i] > 10) { // Игнорируем шум sum += i * dataArray[i]; count += dataArray[i]; } } // Вычисляем среднюю громкость let volumeSum = 0; for (let i = 0; i < bufferLength; i++) { volumeSum += dataArray[i]; } let volumeAvg = volumeSum / bufferLength / 255; if (count > 0) { const normalizedPitch = sum / count / (bufferLength / 8); // Сглаживаем значения для более плавного перехода lastPitch = lastPitch * 0.7 + normalizedPitch * 0.3; lastVolume = lastVolume * 0.7 + volumeAvg * 0.3; // Обновляем отображение текущих значений document.getElementById('pitch-display').textContent = `Тембр: ${lastPitch.toFixed(2)}`; document.getElementById('volume-display').textContent = `Громкость: ${lastVolume.toFixed(2)}`; // Меняем время суток в зависимости от тембра hours = Math.floor(lastPitch * 24); minutes = Math.floor((lastPitch * 24 - hours) * 60); // Обновляем отображение времени document.getElementById('time-display').textContent = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`; // Обновляем сцену updateTimeOfDay(hours, minutes, lastPitch, lastVolume); } } // Инициализация window.onload = function() { setupScene(); updateTimeOfDay(hours, minutes, 0.5, 0.5); // Устанавливаем обработчики событий для кнопок document.getElementById('start-btn').addEventListener('click', startAudioProcessing); document.getElementById('stop-btn').addEventListener('click', stopAudioProcessing); // Устанавливаем интервал для обновления времени даже без звука setInterval(function() { if (!audioContext) { minutes++; if (minutes >= 60) { minutes = 0; hours++; if (hours >= 24) { hours = 0; } } document.getElementById('time-display').textContent = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`; updateTimeOfDay(hours, minutes, hours / 24, 0.5); } }, 1000); }; </script> </body> </html>