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);
|
||||
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -376,6 +376,9 @@ class GameState {
|
|||
if (mapView === null) {
|
||||
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);
|
||||
|
||||
// Camera
|
||||
|
|
@ -386,14 +389,27 @@ class GameState {
|
|||
3000
|
||||
);
|
||||
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.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);
|
||||
|
||||
// Controls
|
||||
// Controls with streaming optimizations
|
||||
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.screenSpacePanning = true;
|
||||
this.camControls.minDistance = 100;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { closeTwoPowerConversation, showTwoPowerConversation } from "./component
|
|||
import { PowerENUM } from "./types/map";
|
||||
import { debugMenuInstance } from "./debug/debugMenu";
|
||||
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
|
||||
// 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() {
|
||||
gameState.createThreeScene()
|
||||
|
||||
// Initialize background audio for streaming mode
|
||||
initializeBackgroundAudio();
|
||||
|
||||
// Enable audio on first user interaction (to comply with browser autoplay policies)
|
||||
let audioEnabled = false;
|
||||
const enableAudio = () => {
|
||||
|
|
@ -35,6 +39,11 @@ function initScene() {
|
|||
silentAudio.volume = 0;
|
||||
silentAudio.play().catch(() => {});
|
||||
|
||||
// Start background audio in streaming mode
|
||||
if (isStreamingMode) {
|
||||
startBackgroundAudio();
|
||||
}
|
||||
|
||||
// Remove the listener after first interaction
|
||||
document.removeEventListener('click', enableAudio);
|
||||
document.removeEventListener('keydown', enableAudio);
|
||||
|
|
@ -78,8 +87,10 @@ function initScene() {
|
|||
}
|
||||
if (isStreamingMode) {
|
||||
setTimeout(() => {
|
||||
togglePlayback()
|
||||
}, 5000) // Increased delay to 5 seconds for Chrome to stabilize
|
||||
togglePlayback();
|
||||
// Try to start background audio when auto-starting
|
||||
startBackgroundAudio();
|
||||
}, 10000) // Increased delay to 10 seconds for Chrome to fully load in Docker
|
||||
}
|
||||
})
|
||||
}).catch(err => {
|
||||
|
|
@ -191,20 +202,25 @@ function animate(currentTime: number = 0) {
|
|||
}, config.effectivePlaybackSpeed);
|
||||
}
|
||||
// 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 => {
|
||||
if (obj.userData.pulseAnimation) {
|
||||
const anim = obj.userData.pulseAnimation;
|
||||
// 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) {
|
||||
const pulseValue = sineWave(config.animation.supplyPulseFrequency, anim.time, anim.intensity, 0.5);
|
||||
obj.userData.glowMesh.material.opacity = 0.2 + (pulseValue * 0.3);
|
||||
const scale = 1 + (pulseValue * 0.1);
|
||||
obj.userData.glowMesh.scale.set(scale, scale, scale);
|
||||
}
|
||||
// Subtle bobbing up/down
|
||||
obj.position.y = 2 + sineWave(config.animation.supplyPulseFrequency, anim.time, 0.5);
|
||||
// Subtle bobbing up/down - reduce in streaming mode
|
||||
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 \
|
||||
--enable-usermedia-screen-capturing \
|
||||
--enable-gpu \
|
||||
--use-gl=swiftshader \
|
||||
--use-gl=angle \
|
||||
--use-angle=gl \
|
||||
--disable-gpu-vsync \
|
||||
--disable-gpu-sandbox \
|
||||
--enable-accelerated-2d-canvas \
|
||||
--enable-accelerated-video-decode=false \
|
||||
--force-device-scale-factor=1 \
|
||||
--disable-web-security \
|
||||
--disable-features=VizDisplayCompositor \
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue