自动切换音效场景脚本怎么写

wen 实用脚本 1

本文目录导读:

自动切换音效场景脚本怎么写

  1. 基于时间自动切换
  2. 基于传感器触发(树莓派示例)
  3. Unity游戏引擎版本(C#)
  4. Web前端版本(JavaScript)
  5. 使用建议

我来帮你编写一个自动切换音效场景的脚本,根据不同的触发条件和应用场景,这里有几种常见的实现方式:

基于时间自动切换

import time
import random
class AudioSceneManager:
    def __init__(self):
        self.scenes = {
            "morning": {
                "bgm": "morning_bgm.mp3",
                "sound_effects": ["birds.mp3", "water_flow.mp3"],
                "volume": 0.7
            },
            "afternoon": {
                "bgm": "afternoon_bgm.mp3",
                "sound_effects": ["wind.mp3", "traffic.mp3"],
                "volume": 0.5
            },
            "evening": {
                "bgm": "evening_bgm.mp3",
                "sound_effects": ["cricket.mp3", "fire.mp3"],
                "volume": 0.6
            },
            "night": {
                "bgm": "night_bgm.mp3",
                "sound_effects": ["owl.mp3", "silence.mp3"],
                "volume": 0.3
            }
        }
        self.current_scene = None
    def get_current_hour_scene(self):
        hour = time.localtime().tm_hour
        if 5 <= hour < 12:
            return "morning"
        elif 12 <= hour < 17:
            return "afternoon"
        elif 17 <= hour < 21:
            return "evening"
        else:
            return "night"
    def switch_scene(self, scene_name):
        if scene_name in self.scenes and scene_name != self.current_scene:
            print(f"切换场景: {scene_name}")
            scene = self.scenes[scene_name]
            # 这里添加实际的音频控制代码
            self.play_scene_sounds(scene)
            self.current_scene = scene_name
    def play_scene_sounds(self, scene):
        # 示例:播放背景音乐和音效
        print(f"播放背景音乐: {scene['bgm']}")
        for effect in scene['sound_effects']:
            print(f"播放音效: {effect}")
        print(f"设置音量: {scene['volume']}")
    def auto_switch(self, check_interval=60):
        """自动检测并切换场景"""
        while True:
            scene_name = self.get_current_hour_scene()
            self.switch_scene(scene_name)
            time.sleep(check_interval)
# 使用示例
manager = AudioSceneManager()
# manager.auto_switch()  # 启动自动切换

基于传感器触发(树莓派示例)

import RPi.GPIO as GPIO
import time
import pygame
class SensorAudioScene:
    def __init__(self):
        GPIO.setmode(GPIO.BCM)
        self.sensors = []
        self.current_scene = "idle"
    def add_sensor(self, pin, scene_name, scene_config):
        GPIO.setup(pin, GPIO.IN)
        self.sensors.append({
            "pin": pin,
            "scene": scene_name,
            "config": scene_config,
            "last_state": GPIO.LOW
        })
    def check_sensors(self):
        for sensor in self.sensors:
            current_state = GPIO.input(sensor["pin"])
            if current_state == GPIO.HIGH and sensor["last_state"] == GPIO.LOW:
                self.switch_scene(sensor["scene"], sensor["config"])
            sensor["last_state"] = current_state
    def switch_scene(self, scene_name, scene_config):
        print(f"切换场景: {scene_name}")
        # 停止当前场景
        if self.current_scene:
            self.stop_scene(self.current_scene)
        # 启动新场景
        self.start_scene(scene_config)
        self.current_scene = scene_name
    def start_scene(self, config):
        # 播放音效
        if "sound" in config:
            pygame.mixer.Sound(config["sound"]).play(-1)
        if "music" in config:
            pygame.mixer.music.load(config["music"])
            pygame.mixer.music.play(-1)
    def stop_scene(self, scene_name):
        pygame.mixer.stop()
        pygame.mixer.music.stop()
    def run(self):
        try:
            while True:
                self.check_sensors()
                time.sleep(0.1)
        except KeyboardInterrupt:
            GPIO.cleanup()
# 使用示例
# sensor_scene = SensorAudioScene()
# sensor_scene.add_sensor(17, "enter_room", {"music": "enter.mp3", "sound": "door.mp3"})
# sensor_scene.add_sensor(18, "leave_room", {"music": "leave.mp3", "sound": "exit.mp3"})
# sensor_scene.run()

Unity游戏引擎版本(C#)

using UnityEngine;
using System.Collections;
public class AutoAudioSceneSwitcher : MonoBehaviour
{
    [System.Serializable]
    public class AudioScene
    {
        public string sceneName;
        public AudioClip backgroundMusic;
        public AudioClip[] ambientSounds;
        [Range(0f, 1f)]
        public float volume = 0.5f;
    }
    public AudioScene[] scenes;
    public float transitionTime = 2f;
    private AudioSource musicSource;
    private AudioSource[] ambientSources;
    private int currentSceneIndex = -1;
    private Coroutine transitionCoroutine;
    void Start()
    {
        // 创建音频源
        musicSource = gameObject.AddComponent<AudioSource>();
        musicSource.loop = true;
        // 创建环境音源
        if (scenes.Length > 0 && scenes[0].ambientSounds.Length > 0)
        {
            ambientSources = new AudioSource[scenes[0].ambientSounds.Length];
            for (int i = 0; i < ambientSources.Length; i++)
            {
                ambientSources[i] = gameObject.AddComponent<AudioSource>();
                ambientSources[i].loop = true;
            }
        }
        // 开始自动切换协程
        StartCoroutine(AutoSwitchRoutine());
    }
    void Update()
    {
        // 手动触发场景切换(可根据游戏逻辑调用)
        if (Input.GetKeyDown(KeyCode.Space))
        {
            int nextScene = (currentSceneIndex + 1) % scenes.Length;
            SwitchToScene(nextScene);
        }
    }
    IEnumerator AutoSwitchRoutine()
    {
        // 每隔30秒自动切换场景(示例)
        while (true)
        {
            yield return new WaitForSeconds(30f);
            int nextScene = Random.Range(0, scenes.Length);
            SwitchToScene(nextScene);
        }
    }
    public void SwitchToScene(int sceneIndex)
    {
        if (sceneIndex < 0 || sceneIndex >= scenes.Length || sceneIndex == currentSceneIndex)
            return;
        if (transitionCoroutine != null)
            StopCoroutine(transitionCoroutine);
        transitionCoroutine = StartCoroutine(TransitionToScene(sceneIndex));
    }
    IEnumerator TransitionToScene(int sceneIndex)
    {
        AudioScene targetScene = scenes[sceneIndex];
        // 淡出当前场景
        if (currentSceneIndex >= 0)
        {
            float startVolume = musicSource.volume;
            float elapsedTime = 0;
            while (elapsedTime < transitionTime)
            {
                elapsedTime += Time.deltaTime;
                float t = elapsedTime / transitionTime;
                // 淡出音乐
                musicSource.volume = Mathf.Lerp(startVolume, 0, t);
                // 淡出环境音
                if (ambientSources != null)
                {
                    float ambientStartVolume = ambientSources[0].volume;
                    foreach (var source in ambientSources)
                    {
                        source.volume = Mathf.Lerp(ambientStartVolume, 0, t);
                    }
                }
                yield return null;
            }
        }
        // 停止当前音频
        musicSource.Stop();
        if (ambientSources != null)
        {
            foreach (var source in ambientSources)
            {
                source.Stop();
            }
        }
        // 设置新场景
        musicSource.clip = targetScene.backgroundMusic;
        musicSource.Play();
        if (ambientSources != null && targetScene.ambientSounds.Length > 0)
        {
            for (int i = 0; i < ambientSources.Length && i < targetScene.ambientSounds.Length; i++)
            {
                ambientSources[i].clip = targetScene.ambientSounds[i];
                ambientSources[i].Play();
            }
        }
        // 淡入新场景
        float targetVolume = targetScene.volume;
        float fadeInTime = 0;
        while (fadeInTime < transitionTime)
        {
            fadeInTime += Time.deltaTime;
            float t = fadeInTime / transitionTime;
            musicSource.volume = Mathf.Lerp(0, targetVolume, t);
            if (ambientSources != null)
            {
                foreach (var source in ambientSources)
                {
                    source.volume = Mathf.Lerp(0, targetVolume * 0.5f, t);
                }
            }
            yield return null;
        }
        currentSceneIndex = sceneIndex;
        transitionCoroutine = null;
    }
    // 外部调用接口
    public void SwitchToSceneByName(string sceneName)
    {
        for (int i = 0; i < scenes.Length; i++)
        {
            if (scenes[i].sceneName == sceneName)
            {
                SwitchToScene(i);
                return;
            }
        }
        Debug.LogWarning($"场景 {sceneName} 未找到");
    }
}

Web前端版本(JavaScript)

class AudioSceneManager {
    constructor() {
        this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
        this.scenes = new Map();
        this.currentScene = null;
        this.bufferCache = new Map();
        this.effects = {
            fadeDuration: 2
        };
        // 初始化场景
        this.initScenes();
        // 监听场景自动切换条件
        this.setupAutoSwitch();
    }
    initScenes() {
        // 添加场景配置
        this.addScene('peaceful', {
            sounds: ['nature.mp3', 'birds.mp3'],
            volume: 0.7,
            trigger: 'time',
            timeRange: { start: 6, end: 18 }
        });
        this.addScene('action', {
            sounds: ['action_music.mp3', 'effects.mp3'],
            volume: 0.9,
            trigger: 'event',
            event: 'combat'
        });
        this.addScene('night', {
            sounds: ['night_bgm.mp3', 'crickets.mp3'],
            volume: 0.3,
            trigger: 'time',
            timeRange: { start: 18, end: 6 }
        });
    }
    async addScene(name, config) {
        this.scenes.set(name, config);
        // 预加载音频
        const buffers = [];
        for (const soundUrl of config.sounds) {
            if (!this.bufferCache.has(soundUrl)) {
                const buffer = await this.loadSound(soundUrl);
                this.bufferCache.set(soundUrl, buffer);
                buffers.push(buffer);
            } else {
                buffers.push(this.bufferCache.get(soundUrl));
            }
        }
        config.buffers = buffers;
    }
    async loadSound(url) {
        const response = await fetch(url);
        const arrayBuffer = await response.arrayBuffer();
        return await this.audioContext.decodeAudioData(arrayBuffer);
    }
    setupAutoSwitch() {
        // 定时检查场景切换
        setInterval(() => {
            this.checkTimeBasedScenes();
        }, 60000); // 每分钟检查一次
        // 监听自定义事件
        document.addEventListener('gameEvent', (event) => {
            this.handleGameEvent(event.detail);
        });
    }
    checkTimeBasedScenes() {
        const currentHour = new Date().getHours();
        for (const [name, config] of this.scenes) {
            if (config.trigger === 'time') {
                const { start, end } = config.timeRange;
                let isInRange;
                if (start <= end) {
                    isInRange = currentHour >= start && currentHour < end;
                } else {
                    // 跨越午夜的情况
                    isInRange = currentHour >= start || currentHour < end;
                }
                if (isInRange && this.currentScene !== name) {
                    this.switchToScene(name);
                    break;
                }
            }
        }
    }
    handleGameEvent(event) {
        console.log('处理游戏事件:', event);
        for (const [name, config] of this.scenes) {
            if (config.trigger === 'event' && config.event === event.type) {
                this.switchToScene(name);
                break;
            }
        }
    }
    async switchToScene(sceneName) {
        if (!this.scenes.has(sceneName) || sceneName === this.currentScene) {
            return;
        }
        const config = this.scenes.get(sceneName);
        console.log(`切换到场景: ${sceneName}`);
        // 淡出当前场景
        await this.fadeOutCurrentScene();
        // 停止所有音频
        this.stopAll();
        // 播放新场景
        await this.playScene(config);
        this.currentScene = sceneName;
        // 触发场景切换事件
        document.dispatchEvent(new CustomEvent('sceneChanged', {
            detail: { scene: sceneName }
        }));
    }
    fadeOutCurrentScene() {
        return new Promise((resolve) => {
            // 实际项目中需要实现渐出效果
            setTimeout(resolve, this.effects.fadeDuration * 1000);
        });
    }
    playScene(config) {
        return new Promise((resolve) => {
            config.buffers.forEach((buffer, index) => {
                const source = this.audioContext.createBufferSource();
                const gainNode = this.audioContext.createGain();
                source.buffer = buffer;
                source.connect(gainNode);
                gainNode.connect(this.audioContext.destination);
                gainNode.gain.value = config.volume / config.buffers.length;
                source.start(0);
                // 保存引用以便停止
                this.activeSources.push(source);
            });
            setTimeout(resolve, 100);
        });
    }
    stopAll() {
        this.activeSources.forEach(source => {
            try {
                source.stop();
            } catch (e) {
                // 忽略已停止的源
            }
        });
        this.activeSources = [];
    }
}
// 使用示例
const audioManager = new AudioSceneManager();
// 手动触发场景切换
audioManager.switchToScene('action');
// 手动触发游戏事件
document.dispatchEvent(new CustomEvent('gameEvent', { 
    detail: { type: 'combat' } 
}));

使用建议

  1. 选择合适的方式

    • 时间自动切换:适用于日常环境音效
    • 传感器触发:适合物理交互场景
    • 游戏事件触发:适合游戏中的动态场景切换
  2. 性能优化

    • 预加载音频资源
    • 使用音频池管理多个音源
    • 实现平滑过渡效果
  3. 扩展功能

    • 添加音量渐变和混音
    • 实现场景优先级系统
    • 支持用户手动切换

你可以根据具体的使用环境选择最适合的版本,需要我针对某个特定平台或需求进行修改吗?

抱歉,评论功能暂时关闭!