1use bevy::{audio::Volume, prelude::*};
5
6fn main() {
7 App::new()
8 .add_plugins(DefaultPlugins)
9 .add_systems(Startup, setup)
10 .add_systems(Update, (cycle_game_state, fade_in, fade_out))
11 .add_systems(Update, change_track)
12 .run();
13}
14
15#[derive(Resource, Default)]
17enum GameState {
18 #[default]
19 Peaceful,
20 Battle,
21}
22
23#[derive(Resource)]
25struct GameStateTimer(Timer);
26
27#[derive(Resource)]
29struct SoundtrackPlayer {
30 track_list: Vec<Handle<AudioSource>>,
31}
32
33impl SoundtrackPlayer {
34 fn new(track_list: Vec<Handle<AudioSource>>) -> Self {
35 Self { track_list }
36 }
37}
38
39#[derive(Component)]
41struct FadeIn;
42
43#[derive(Component)]
45struct FadeOut;
46
47fn setup(asset_server: Res<AssetServer>, mut commands: Commands) {
48 commands.insert_resource(GameState::default());
50 commands.insert_resource(GameStateTimer(Timer::from_seconds(
51 10.0,
52 TimerMode::Repeating,
53 )));
54
55 let track_1 = asset_server.load::<AudioSource>("sounds/Mysterious acoustic guitar.ogg");
57 let track_2 = asset_server.load::<AudioSource>("sounds/Epic orchestra music.ogg");
58 let track_list = vec![track_1, track_2];
59 commands.insert_resource(SoundtrackPlayer::new(track_list));
60}
61
62fn change_track(
64 mut commands: Commands,
65 soundtrack_player: Res<SoundtrackPlayer>,
66 soundtrack: Query<Entity, With<AudioSink>>,
67 game_state: Res<GameState>,
68) {
69 if game_state.is_changed() {
70 for track in soundtrack.iter() {
72 commands.entity(track).insert(FadeOut);
73 }
74
75 let track = match game_state.as_ref() {
80 GameState::Peaceful => soundtrack_player.track_list.first().unwrap().clone(),
81 GameState::Battle => soundtrack_player.track_list.get(1).unwrap().clone(),
82 };
83
84 commands.spawn((
85 AudioPlayer(track),
86 PlaybackSettings {
87 mode: bevy::audio::PlaybackMode::Loop,
88 volume: Volume::SILENT,
89 ..default()
90 },
91 FadeIn,
92 ));
93 }
94}
95
96const FADE_TIME: f32 = 2.0;
98
99fn fade_in(
102 mut commands: Commands,
103 mut audio_sink: Query<(&mut AudioSink, Entity), With<FadeIn>>,
104 timer: Res<GameStateTimer>,
105) {
106 for (mut audio, entity) in audio_sink.iter_mut() {
107 audio.set_volume(
108 Volume::SILENT.fade_towards(Volume::Linear(1.0), timer.0.elapsed_secs() / FADE_TIME),
109 );
110 if timer.0.elapsed_secs() >= FADE_TIME {
111 audio.set_volume(Volume::Linear(1.0));
112 commands.entity(entity).remove::<FadeIn>();
113 }
114 }
115}
116
117fn fade_out(
120 mut commands: Commands,
121 mut audio_sink: Query<(&mut AudioSink, Entity), With<FadeOut>>,
122 timer: Res<GameStateTimer>,
123) {
124 for (mut audio, entity) in audio_sink.iter_mut() {
125 audio.set_volume(
126 Volume::Linear(1.0).fade_towards(Volume::SILENT, timer.0.elapsed_secs() / FADE_TIME),
127 );
128 if timer.0.elapsed_secs() >= FADE_TIME {
129 commands.entity(entity).despawn();
130 }
131 }
132}
133
134fn cycle_game_state(
136 mut timer: ResMut<GameStateTimer>,
137 mut game_state: ResMut<GameState>,
138 time: Res<Time>,
139) {
140 timer.0.tick(time.delta());
141 if timer.0.just_finished() {
142 match game_state.as_ref() {
143 GameState::Battle => *game_state = GameState::Peaceful,
144 GameState::Peaceful => *game_state = GameState::Battle,
145 }
146 }
147}