use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, (cycle_game_state, fade_in, fade_out))
.add_systems(Update, change_track)
.run();
}
#[derive(Resource, Default)]
enum GameState {
#[default]
Peaceful,
Battle,
}
#[derive(Resource)]
struct GameStateTimer(Timer);
#[derive(Resource)]
struct SoundtrackPlayer {
track_list: Vec<Handle<AudioSource>>,
}
impl SoundtrackPlayer {
fn new(track_list: Vec<Handle<AudioSource>>) -> Self {
Self { track_list }
}
}
#[derive(Component)]
struct FadeIn;
#[derive(Component)]
struct FadeOut;
fn setup(asset_server: Res<AssetServer>, mut commands: Commands) {
commands.insert_resource(GameState::default());
commands.insert_resource(GameStateTimer(Timer::from_seconds(
10.0,
TimerMode::Repeating,
)));
let track_1 = asset_server.load::<AudioSource>("sounds/Mysterious acoustic guitar.ogg");
let track_2 = asset_server.load::<AudioSource>("sounds/Epic orchestra music.ogg");
let track_list = vec![track_1, track_2];
commands.insert_resource(SoundtrackPlayer::new(track_list));
}
fn change_track(
mut commands: Commands,
soundtrack_player: Res<SoundtrackPlayer>,
soundtrack: Query<Entity, With<AudioSink>>,
game_state: Res<GameState>,
) {
if game_state.is_changed() {
for track in soundtrack.iter() {
commands.entity(track).insert(FadeOut);
}
match game_state.as_ref() {
GameState::Peaceful => {
commands.spawn((
AudioPlayer(soundtrack_player.track_list.first().unwrap().clone()),
PlaybackSettings {
mode: bevy::audio::PlaybackMode::Loop,
volume: bevy::audio::Volume::ZERO,
..default()
},
FadeIn,
));
}
GameState::Battle => {
commands.spawn((
AudioPlayer(soundtrack_player.track_list.get(1).unwrap().clone()),
PlaybackSettings {
mode: bevy::audio::PlaybackMode::Loop,
volume: bevy::audio::Volume::ZERO,
..default()
},
FadeIn,
));
}
}
}
}
const FADE_TIME: f32 = 2.0;
fn fade_in(
mut commands: Commands,
mut audio_sink: Query<(&mut AudioSink, Entity), With<FadeIn>>,
time: Res<Time>,
) {
for (audio, entity) in audio_sink.iter_mut() {
audio.set_volume(audio.volume() + time.delta_secs() / FADE_TIME);
if audio.volume() >= 1.0 {
audio.set_volume(1.0);
commands.entity(entity).remove::<FadeIn>();
}
}
}
fn fade_out(
mut commands: Commands,
mut audio_sink: Query<(&mut AudioSink, Entity), With<FadeOut>>,
time: Res<Time>,
) {
for (audio, entity) in audio_sink.iter_mut() {
audio.set_volume(audio.volume() - time.delta_secs() / FADE_TIME);
if audio.volume() <= 0.0 {
commands.entity(entity).despawn_recursive();
}
}
}
fn cycle_game_state(
mut timer: ResMut<GameStateTimer>,
mut game_state: ResMut<GameState>,
time: Res<Time>,
) {
timer.0.tick(time.delta());
if timer.0.just_finished() {
match game_state.as_ref() {
GameState::Battle => *game_state = GameState::Peaceful,
GameState::Peaceful => *game_state = GameState::Battle,
}
}
}