mirror of
https://github.com/GoodStartLabs/AI_Diplomacy.git
synced 2026-04-19 12:58:09 +00:00
added background music
This commit is contained in:
parent
30849a36e4
commit
ad3af94f72
6 changed files with 125 additions and 12 deletions
BIN
ai_animation/public/sounds/background_ambience.mp3
Normal file
BIN
ai_animation/public/sounds/background_ambience.mp3
Normal file
Binary file not shown.
69
ai_animation/src/backgroundAudio.ts
Normal file
69
ai_animation/src/backgroundAudio.ts
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
/**
|
||||||
|
* Background audio management for streaming mode
|
||||||
|
*/
|
||||||
|
|
||||||
|
let backgroundAudio: HTMLAudioElement | null = null;
|
||||||
|
let isAudioInitialized = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize background audio for streaming
|
||||||
|
* Only loads in streaming mode to avoid unnecessary downloads
|
||||||
|
*/
|
||||||
|
export function initializeBackgroundAudio(): void {
|
||||||
|
const isStreamingMode = import.meta.env.VITE_STREAMING_MODE === 'True' || import.meta.env.VITE_STREAMING_MODE === 'true';
|
||||||
|
|
||||||
|
if (!isStreamingMode || isAudioInitialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isAudioInitialized = true;
|
||||||
|
|
||||||
|
// Create audio element
|
||||||
|
backgroundAudio = new Audio();
|
||||||
|
backgroundAudio.loop = true;
|
||||||
|
backgroundAudio.volume = 0.4; // 40% volume as requested
|
||||||
|
|
||||||
|
// For now, we'll use a placeholder - you should download and convert the wave file
|
||||||
|
// to a smaller MP3 format (aim for < 10MB) and place it in public/sounds/
|
||||||
|
backgroundAudio.src = './sounds/background_ambience.mp3';
|
||||||
|
|
||||||
|
// Handle audio loading
|
||||||
|
backgroundAudio.addEventListener('canplaythrough', () => {
|
||||||
|
console.log('Background audio loaded and ready to play');
|
||||||
|
});
|
||||||
|
|
||||||
|
backgroundAudio.addEventListener('error', (e) => {
|
||||||
|
console.error('Failed to load background audio:', e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start playing background audio
|
||||||
|
* Will only work after user interaction due to browser policies
|
||||||
|
*/
|
||||||
|
export function startBackgroundAudio(): void {
|
||||||
|
if (backgroundAudio && backgroundAudio.paused) {
|
||||||
|
backgroundAudio.play().catch(err => {
|
||||||
|
console.log('Background audio autoplay blocked, will retry on user interaction:', err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop background audio
|
||||||
|
*/
|
||||||
|
export function stopBackgroundAudio(): void {
|
||||||
|
if (backgroundAudio && !backgroundAudio.paused) {
|
||||||
|
backgroundAudio.pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set background audio volume
|
||||||
|
* @param volume - Volume level from 0 to 1
|
||||||
|
*/
|
||||||
|
export function setBackgroundAudioVolume(volume: number): void {
|
||||||
|
if (backgroundAudio) {
|
||||||
|
backgroundAudio.volume = Math.max(0, Math.min(1, volume));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -404,7 +404,15 @@ function animateMessageWords(message: string, contentSpanId: string, targetPower
|
||||||
setTimeout(addNextWord, delay);
|
setTimeout(addNextWord, delay);
|
||||||
|
|
||||||
// Scroll to ensure newest content is visible
|
// Scroll to ensure newest content is visible
|
||||||
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
// Use requestAnimationFrame to batch DOM updates in streaming mode
|
||||||
|
const isStreamingModeForScroll = import.meta.env.VITE_STREAMING_MODE === 'True' || import.meta.env.VITE_STREAMING_MODE === 'true';
|
||||||
|
if (isStreamingModeForScroll) {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Start animation
|
// Start animation
|
||||||
|
|
|
||||||
|
|
@ -376,6 +376,9 @@ class GameState {
|
||||||
if (mapView === null) {
|
if (mapView === null) {
|
||||||
throw Error("Cannot find mapView element, unable to continue.")
|
throw Error("Cannot find mapView element, unable to continue.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isStreamingMode = import.meta.env.VITE_STREAMING_MODE === 'True' || import.meta.env.VITE_STREAMING_MODE === 'true';
|
||||||
|
|
||||||
this.scene.background = new THREE.Color(0x87CEEB);
|
this.scene.background = new THREE.Color(0x87CEEB);
|
||||||
|
|
||||||
// Camera
|
// Camera
|
||||||
|
|
@ -386,14 +389,27 @@ class GameState {
|
||||||
3000
|
3000
|
||||||
);
|
);
|
||||||
this.camera.position.set(0, 800, 900); // MODIFIED: Increased z-value to account for map shift
|
this.camera.position.set(0, 800, 900); // MODIFIED: Increased z-value to account for map shift
|
||||||
this.renderer = new THREE.WebGLRenderer({ antialias: true });
|
|
||||||
|
// Renderer with streaming optimizations
|
||||||
|
this.renderer = new THREE.WebGLRenderer({
|
||||||
|
antialias: !isStreamingMode, // Disable antialiasing in streaming mode
|
||||||
|
powerPreference: "high-performance",
|
||||||
|
preserveDrawingBuffer: isStreamingMode // Required for streaming
|
||||||
|
});
|
||||||
this.renderer.setSize(mapView.clientWidth, mapView.clientHeight);
|
this.renderer.setSize(mapView.clientWidth, mapView.clientHeight);
|
||||||
this.renderer.setPixelRatio(window.devicePixelRatio);
|
|
||||||
|
// Force lower pixel ratio for streaming to reduce GPU load
|
||||||
|
if (isStreamingMode) {
|
||||||
|
this.renderer.setPixelRatio(1);
|
||||||
|
} else {
|
||||||
|
this.renderer.setPixelRatio(window.devicePixelRatio);
|
||||||
|
}
|
||||||
|
|
||||||
mapView.appendChild(this.renderer.domElement);
|
mapView.appendChild(this.renderer.domElement);
|
||||||
|
|
||||||
// Controls
|
// Controls with streaming optimizations
|
||||||
this.camControls = new OrbitControls(this.camera, this.renderer.domElement);
|
this.camControls = new OrbitControls(this.camera, this.renderer.domElement);
|
||||||
this.camControls.enableDamping = true;
|
this.camControls.enableDamping = !isStreamingMode; // Disable damping for immediate response
|
||||||
this.camControls.dampingFactor = 0.05;
|
this.camControls.dampingFactor = 0.05;
|
||||||
this.camControls.screenSpacePanning = true;
|
this.camControls.screenSpacePanning = true;
|
||||||
this.camControls.minDistance = 100;
|
this.camControls.minDistance = 100;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import { closeTwoPowerConversation, showTwoPowerConversation } from "./component
|
||||||
import { PowerENUM } from "./types/map";
|
import { PowerENUM } from "./types/map";
|
||||||
import { debugMenuInstance } from "./debug/debugMenu";
|
import { debugMenuInstance } from "./debug/debugMenu";
|
||||||
import { sineWave } from "./utils/timing";
|
import { sineWave } from "./utils/timing";
|
||||||
|
import { initializeBackgroundAudio, startBackgroundAudio } from "./backgroundAudio";
|
||||||
|
|
||||||
//TODO: Create a function that finds a suitable unit location within a given polygon, for placing units better
|
//TODO: Create a function that finds a suitable unit location within a given polygon, for placing units better
|
||||||
// Currently the location for label, unit, and SC are all the same manually picked location
|
// Currently the location for label, unit, and SC are all the same manually picked location
|
||||||
|
|
@ -24,6 +25,9 @@ const isStreamingMode = import.meta.env.VITE_STREAMING_MODE === 'True' || import
|
||||||
function initScene() {
|
function initScene() {
|
||||||
gameState.createThreeScene()
|
gameState.createThreeScene()
|
||||||
|
|
||||||
|
// Initialize background audio for streaming mode
|
||||||
|
initializeBackgroundAudio();
|
||||||
|
|
||||||
// Enable audio on first user interaction (to comply with browser autoplay policies)
|
// Enable audio on first user interaction (to comply with browser autoplay policies)
|
||||||
let audioEnabled = false;
|
let audioEnabled = false;
|
||||||
const enableAudio = () => {
|
const enableAudio = () => {
|
||||||
|
|
@ -35,6 +39,11 @@ function initScene() {
|
||||||
silentAudio.volume = 0;
|
silentAudio.volume = 0;
|
||||||
silentAudio.play().catch(() => {});
|
silentAudio.play().catch(() => {});
|
||||||
|
|
||||||
|
// Start background audio in streaming mode
|
||||||
|
if (isStreamingMode) {
|
||||||
|
startBackgroundAudio();
|
||||||
|
}
|
||||||
|
|
||||||
// Remove the listener after first interaction
|
// Remove the listener after first interaction
|
||||||
document.removeEventListener('click', enableAudio);
|
document.removeEventListener('click', enableAudio);
|
||||||
document.removeEventListener('keydown', enableAudio);
|
document.removeEventListener('keydown', enableAudio);
|
||||||
|
|
@ -78,8 +87,10 @@ function initScene() {
|
||||||
}
|
}
|
||||||
if (isStreamingMode) {
|
if (isStreamingMode) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
togglePlayback()
|
togglePlayback();
|
||||||
}, 5000) // Increased delay to 5 seconds for Chrome to stabilize
|
// Try to start background audio when auto-starting
|
||||||
|
startBackgroundAudio();
|
||||||
|
}, 10000) // Increased delay to 10 seconds for Chrome to fully load in Docker
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
|
|
@ -191,20 +202,25 @@ function animate(currentTime: number = 0) {
|
||||||
}, config.effectivePlaybackSpeed);
|
}, config.effectivePlaybackSpeed);
|
||||||
}
|
}
|
||||||
// Update any pulsing or wave animations on supply centers or units
|
// Update any pulsing or wave animations on supply centers or units
|
||||||
if (gameState.scene.userData.animatedObjects) {
|
// In streaming mode, reduce animation frequency
|
||||||
|
const isStreamingMode = import.meta.env.VITE_STREAMING_MODE === 'True' || import.meta.env.VITE_STREAMING_MODE === 'true';
|
||||||
|
const frameSkip = isStreamingMode ? 2 : 1; // Skip every other frame in streaming
|
||||||
|
|
||||||
|
if (gameState.scene.userData.animatedObjects && (Math.floor(currentTime / 16.67) % frameSkip === 0)) {
|
||||||
gameState.scene.userData.animatedObjects.forEach(obj => {
|
gameState.scene.userData.animatedObjects.forEach(obj => {
|
||||||
if (obj.userData.pulseAnimation) {
|
if (obj.userData.pulseAnimation) {
|
||||||
const anim = obj.userData.pulseAnimation;
|
const anim = obj.userData.pulseAnimation;
|
||||||
// Use delta time for consistent animation speed regardless of frame rate
|
// Use delta time for consistent animation speed regardless of frame rate
|
||||||
anim.time += anim.speed * deltaTime;
|
anim.time += anim.speed * deltaTime * frameSkip; // Compensate for skipped frames
|
||||||
if (obj.userData.glowMesh) {
|
if (obj.userData.glowMesh) {
|
||||||
const pulseValue = sineWave(config.animation.supplyPulseFrequency, anim.time, anim.intensity, 0.5);
|
const pulseValue = sineWave(config.animation.supplyPulseFrequency, anim.time, anim.intensity, 0.5);
|
||||||
obj.userData.glowMesh.material.opacity = 0.2 + (pulseValue * 0.3);
|
obj.userData.glowMesh.material.opacity = 0.2 + (pulseValue * 0.3);
|
||||||
const scale = 1 + (pulseValue * 0.1);
|
const scale = 1 + (pulseValue * 0.1);
|
||||||
obj.userData.glowMesh.scale.set(scale, scale, scale);
|
obj.userData.glowMesh.scale.set(scale, scale, scale);
|
||||||
}
|
}
|
||||||
// Subtle bobbing up/down
|
// Subtle bobbing up/down - reduce in streaming mode
|
||||||
obj.position.y = 2 + sineWave(config.animation.supplyPulseFrequency, anim.time, 0.5);
|
const bobAmount = isStreamingMode ? 0.25 : 0.5;
|
||||||
|
obj.position.y = 2 + sineWave(config.animation.supplyPulseFrequency, anim.time, bobAmount);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,12 @@ while true; do
|
||||||
--use-fake-ui-for-media-stream \
|
--use-fake-ui-for-media-stream \
|
||||||
--enable-usermedia-screen-capturing \
|
--enable-usermedia-screen-capturing \
|
||||||
--enable-gpu \
|
--enable-gpu \
|
||||||
--use-gl=swiftshader \
|
--use-gl=angle \
|
||||||
|
--use-angle=gl \
|
||||||
--disable-gpu-vsync \
|
--disable-gpu-vsync \
|
||||||
|
--disable-gpu-sandbox \
|
||||||
|
--enable-accelerated-2d-canvas \
|
||||||
|
--enable-accelerated-video-decode=false \
|
||||||
--force-device-scale-factor=1 \
|
--force-device-scale-factor=1 \
|
||||||
--disable-web-security \
|
--disable-web-security \
|
||||||
--disable-features=VizDisplayCompositor \
|
--disable-features=VizDisplayCompositor \
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue