VSteam / index.html
VSPAN's picture
Update index.html
9cd9b33 verified
raw
history blame
19.3 kB
<!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>