Skip to content

Commit

Permalink
Add synced music
Browse files Browse the repository at this point in the history
  • Loading branch information
benfrankel committed Jul 27, 2024
1 parent a15a7ad commit 26cb87d
Show file tree
Hide file tree
Showing 19 changed files with 172 additions and 138 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ jobs:
- name: Add assets to package
run: |
rm -rf '${{ env.ASSETS_DIR }}'/**/*.aseprite '${{ env.ASSETS_DIR }}/mockup'
rm -rf '${{ env.ASSETS_DIR }}'/**/*.{aseprite,wav} '${{ env.ASSETS_DIR }}/mockup'
cp -r '${{ env.ASSETS_DIR }}' '${{ env.OUT_DIR }}' || true # Ignore error if there's nothing to copy
- name: Add web content to package (Web)
Expand Down
Binary file added assets/audio/music/Menu Theme.ogg
Binary file not shown.
Binary file added assets/audio/music/Menu Theme.wav
Binary file not shown.
4 changes: 4 additions & 0 deletions assets/config/audio.ron
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(
bpm: 122,
first_beat: 0.2,
)
3 changes: 0 additions & 3 deletions assets/config/music.ron

This file was deleted.

4 changes: 2 additions & 2 deletions src/game.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub mod actor;
pub mod card;
pub mod cleanup;
pub mod combat;
pub mod music;
pub mod audio;
pub mod spotlight;
pub mod sprite;
pub mod wave;
Expand All @@ -27,7 +27,7 @@ pub(super) fn plugin(app: &mut App) {
card::plugin,
cleanup::plugin,
combat::plugin,
music::plugin,
audio::plugin,
spotlight::plugin,
sprite::plugin,
wave::plugin,
Expand Down
26 changes: 26 additions & 0 deletions src/game/audio.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
pub mod music;

use bevy::prelude::*;
use serde::Deserialize;
use serde::Serialize;

use crate::util::prelude::*;

pub(super) fn plugin(app: &mut App) {
app.configure::<ConfigHandle<AudioConfig>>();

app.add_plugins(music::plugin);
}

#[derive(Asset, Reflect, Serialize, Deserialize)]
pub struct AudioConfig {
/// The precise beats-per-minute of the music.
pub bpm: f64,
/// The position (in seconds) of the first beat.
pub first_beat: f64,
}

impl Config for AudioConfig {
const PATH: &'static str = "config/audio.ron";
const EXTENSION: &'static str = "audio.ron";
}
116 changes: 116 additions & 0 deletions src/game/audio/music.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use bevy::prelude::*;
use bevy_kira_audio::prelude::*;
use pyri_state::prelude::*;

use crate::core::pause::Pause;
use crate::core::UpdateSet;
use crate::game::audio::AudioConfig;
use crate::screen::playing::PlayingAssets;
use crate::screen::Screen;
use crate::util::prelude::*;

pub(super) fn plugin(app: &mut App) {
app.configure::<(MusicHandle, Beat)>();
}

#[derive(Resource, Reflect, Default)]
#[reflect(Resource)]
pub struct MusicHandle(pub Handle<AudioInstance>);

impl Configure for MusicHandle {
fn configure(app: &mut App) {
app.register_type::<Self>();
app.init_resource::<Self>();
app.add_systems(Startup, spawn_music);
app.add_systems(
StateFlush,
Pause.on_edge(
// TODO: Unfortunate that this run condition is necessary...
unpause_music.run_if(Screen::Playing.will_enter()),
pause_music,
),
);
}
}

fn spawn_music(mut commands: Commands, audio: Res<Audio>, assets: Res<PlayingAssets>) {
let handle = audio
.play(assets.music.clone())
.with_volume(0.9)
.loop_until(126.1)
.paused()
.handle();
commands.insert_resource(MusicHandle(handle));
}

pub fn start_music(
music_handle: Res<MusicHandle>,
mut audio_instances: ResMut<Assets<AudioInstance>>,
) {
let music = r!(audio_instances.get_mut(&music_handle.0));
music.seek_to(0.0);
music.resume(AudioTween::default());
}

pub fn pause_music(
music_handle: Res<MusicHandle>,
mut audio_instances: ResMut<Assets<AudioInstance>>,
) {
let music = r!(audio_instances.get_mut(&music_handle.0));
music.pause(AudioTween::default());
}

fn unpause_music(
music_handle: Res<MusicHandle>,
mut audio_instances: ResMut<Assets<AudioInstance>>,
) {
let music = r!(audio_instances.get_mut(&music_handle.0));
music.resume(AudioTween::default());
}

#[derive(Resource, Reflect, Default)]
#[reflect(Resource)]
pub struct Beat {
/// The total number of eighth-beats counted.
pub total: usize,
/// The number of new eighth-beats finished this tick (usually 0 or 1).
pub this_tick: usize,
}

impl Configure for Beat {
fn configure(app: &mut App) {
app.register_type::<Self>();
app.init_resource::<Self>();
app.add_systems(Update, update_beat.in_set(UpdateSet::SyncEarly));
}
}

fn update_beat(
config: ConfigRef<AudioConfig>,
music_handle: Res<MusicHandle>,
audio_instances: ResMut<Assets<AudioInstance>>,
mut beat: ResMut<Beat>,
) {
let config = r!(config.get());
let music = r!(audio_instances.get(&music_handle.0));

let position = music.state().position().unwrap_or(0.0);
let real_beats = ((position - config.first_beat) * config.bpm * 8.0 / 60.0) as usize;

beat.this_tick = real_beats.saturating_sub(beat.total);
beat.total = real_beats;
}

/// A run condition to run a system every `n` eighth-beats.
pub fn on_beat(n: usize) -> impl Fn(Res<Beat>) -> bool {
move |beat| {
let hi = beat.total;
let lo = hi - beat.this_tick;
hi / n > lo / n
}
}

/// A run condition to run a system every `n` beats.
pub fn on_full_beat(n: usize) -> impl Fn(Res<Beat>) -> bool {
on_beat(8 * n)
}
2 changes: 1 addition & 1 deletion src/game/card/attack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use crate::core::UpdateSet;
use crate::game::actor::attack::Attack;
use crate::game::actor::attack::AttackController;
use crate::game::actor::facing::Facing;
use crate::game::audio::music::on_beat;
use crate::game::cleanup::RemoveOnBeat;
use crate::game::music::beat::on_beat;
use crate::util::prelude::*;

pub(super) fn plugin(app: &mut App) {
Expand Down
4 changes: 2 additions & 2 deletions src/game/card/deck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use bevy::prelude::*;
use serde::Deserialize;
use serde::Serialize;

use super::CardConfig;
use crate::core::UpdateSet;
use crate::game::audio::music::on_full_beat;
use crate::game::card::card;
use crate::game::music::beat::on_full_beat;
use crate::game::card::CardConfig;
use crate::util::prelude::*;

pub(super) fn plugin(app: &mut App) {
Expand Down
2 changes: 1 addition & 1 deletion src/game/cleanup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use crate::core::camera::CameraRoot;
use crate::core::pause::Pause;
use crate::core::PostTransformSet;
use crate::core::UpdateSet;
use crate::game::audio::music::on_beat;
use crate::game::combat::hit::OnHit;
use crate::game::music::beat::on_beat;
use crate::util::prelude::*;

pub(super) fn plugin(app: &mut App) {
Expand Down
33 changes: 0 additions & 33 deletions src/game/music.rs

This file was deleted.

85 changes: 0 additions & 85 deletions src/game/music/beat.rs

This file was deleted.

4 changes: 2 additions & 2 deletions src/game/spotlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ use rand::Rng as _;
use serde::Deserialize;
use serde::Serialize;

use super::cleanup::DespawnRadiusSq;
use crate::core::camera::CameraRoot;
use crate::core::pause::Pause;
use crate::core::PostColorSet;
use crate::core::PostTransformSet;
use crate::core::UpdateSet;
use crate::game::music::beat::on_beat;
use crate::game::audio::music::on_beat;
use crate::game::cleanup::DespawnRadiusSq;
use crate::game::GameRoot;
use crate::screen::playing::PlayingAssets;
use crate::util::prelude::*;
Expand Down
4 changes: 2 additions & 2 deletions src/game/sprite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use serde::Deserialize;
use serde::Serialize;

use crate::core::UpdateSet;
use crate::game::music::beat::on_beat;
use crate::game::music::beat::Beat;
use crate::game::audio::music::on_beat;
use crate::game::audio::music::Beat;
use crate::util::prelude::*;

pub(super) fn plugin(app: &mut App) {
Expand Down
2 changes: 1 addition & 1 deletion src/game/wave.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::core::camera::CameraRoot;
use crate::core::UpdateSet;
use crate::game::actor::enemy::enemy;
use crate::game::actor::level::Level;
use crate::game::music::beat::on_full_beat;
use crate::game::audio::music::on_full_beat;
use crate::screen::Screen;
use crate::util::prelude::*;

Expand Down
4 changes: 2 additions & 2 deletions src/screen/loading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use pyri_state::prelude::*;
use crate::game::actor::health::HealthConfig;
use crate::game::actor::level::LevelConfig;
use crate::game::actor::ActorConfig;
use crate::game::audio::AudioConfig;
use crate::game::card::CardConfig;
use crate::game::combat::projectile::ProjectileConfig;
use crate::game::music::MusicConfig;
use crate::game::wave::WaveConfig;
use crate::screen::fade_in;
use crate::screen::fade_out;
Expand All @@ -32,7 +32,7 @@ pub(super) fn plugin(app: &mut App) {
CardConfig::progress.track_progress(),
HealthConfig::progress.track_progress(),
LevelConfig::progress.track_progress(),
MusicConfig::progress.track_progress(),
AudioConfig::progress.track_progress(),
ProjectileConfig::progress.track_progress(),
WaveConfig::progress.track_progress(),
)),
Expand Down
Loading

0 comments on commit 26cb87d

Please sign in to comment.