Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Web builds #91

Merged
merged 7 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[target.wasm32-unknown-unknown]
runner = "wasm-server-runner"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# will have compiled files and executables
debug/
target/
dist/

# These are backup files generated by rustfmt
**/*.rs.bk
Expand Down
19 changes: 19 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ bevy_particle_systems = "0.11.1"
noise = "0.8.2"
rand = "0.8.5"
pathfinding = "4.3.3"
bevy_embedded_assets = "0.9.1"

[profile.dev.package."*"]
opt-level = 3
Expand Down
2 changes: 2 additions & 0 deletions Trunk.itch.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
public_url = "./"
Empty file added index.html
Empty file.
157 changes: 135 additions & 22 deletions src/audio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ impl Plugin for AudioPlugin {
app.add_event::<PlaySoundEffectEvent>();
app.add_event::<StopMusicEvent>();
app.init_resource::<AudioLoadStates>();
app.init_resource::<MusicFolderHandle>();
app.init_resource::<SoundEffectFolderHandle>();
app.init_resource::<MusicHandles>();
app.init_resource::<SoundEffectHandles>();
app.add_systems(Startup, (load_music_files, load_sound_effect_files));
app.add_systems(
Update,
Expand All @@ -38,33 +38,64 @@ impl Plugin for AudioPlugin {
}
}

#[derive(PartialEq)]
enum AudioLoadState {
NotLoaded,
Loading,
Loaded,
Failed,
}

impl Default for AudioLoadState {
fn default() -> Self {
Self::NotLoaded
}
}

impl From<RecursiveDependencyLoadState> for AudioLoadState {
fn from(value: RecursiveDependencyLoadState) -> Self {
match value {
RecursiveDependencyLoadState::NotLoaded => Self::NotLoaded,
RecursiveDependencyLoadState::Loading => Self::Loading,
RecursiveDependencyLoadState::Loaded => Self::Loaded,
RecursiveDependencyLoadState::Failed => Self::Failed,
}
}
}

#[derive(Resource, PartialEq)]
struct AudioLoadStates {
sound_effects_load_state: RecursiveDependencyLoadState,
music_load_state: RecursiveDependencyLoadState,
sound_effects_load_state: AudioLoadState,
music_load_state: AudioLoadState,
}

impl Default for AudioLoadStates {
fn default() -> Self {
Self {
sound_effects_load_state: RecursiveDependencyLoadState::NotLoaded,
music_load_state: RecursiveDependencyLoadState::NotLoaded,
sound_effects_load_state: AudioLoadState::NotLoaded,
music_load_state: AudioLoadState::NotLoaded,
}
}
}

impl AudioLoadStates {
pub const LOADED: Self = Self {
music_load_state: RecursiveDependencyLoadState::Loaded,
sound_effects_load_state: RecursiveDependencyLoadState::Loaded,
music_load_state: AudioLoadState::Loaded,
sound_effects_load_state: AudioLoadState::Loaded,
};
}

#[derive(Resource, Default, Deref, DerefMut)]
struct MusicFolderHandle(Handle<LoadedFolder>);
struct MusicHandles(
#[cfg(not(target_family = "wasm"))] Handle<LoadedFolder>,
#[cfg(target_family = "wasm")] Vec<Handle<AudioSource>>,
);

#[derive(Resource, Default, Deref, DerefMut)]
struct SoundEffectFolderHandle(Handle<LoadedFolder>);
struct SoundEffectHandles(
#[cfg(not(target_family = "wasm"))] Handle<LoadedFolder>,
#[cfg(target_family = "wasm")] Vec<Handle<AudioSource>>,
);

#[derive(Event)]
pub struct PlayMusicEvent {
Expand Down Expand Up @@ -149,7 +180,7 @@ fn handle_play_music_events(
spatial_transform,
} = event;
let settings = settings.unwrap_or(PlaybackSettings::DESPAWN);
let path = format!("{ASSET_FOLDER_MUSIC}/{file_name}");
let path = format_music_file_name(file_name);
let source = asset_server.get_handle(path).unwrap_or_default();
let mut entity = commands.spawn((BackgroundMusic, AudioBundle { source, settings }));

Expand Down Expand Up @@ -183,7 +214,7 @@ fn handle_play_sound_effect_events(
spatial_transform,
} = event;
let settings = settings.unwrap_or(PlaybackSettings::DESPAWN);
let path = format!("{ASSET_FOLDER_SFX}/{file_name}");
let path = format_sfx_file_name(file_name);
let source = asset_server.get_handle(path).unwrap_or_default();
let mut entity = commands.spawn((AudioBundle { source, settings }, SoundEffect));

Expand All @@ -194,33 +225,115 @@ fn handle_play_sound_effect_events(
}

fn load_music_files(mut commands: Commands, asset_server: Res<AssetServer>) {
let music_folder_handle = asset_server.load_folder(ASSET_FOLDER_MUSIC);
commands.insert_resource(MusicFolderHandle(music_folder_handle));
let music_handles = {
#[cfg(not(target_family = "wasm"))]
{
asset_server.load_folder(ASSET_FOLDER_MUSIC)
}

#[cfg(target_family = "wasm")]
{
let asset_music_list = [
format_music_file_name("theme1.ogg"),
format_music_file_name("theme2.ogg"),
format_music_file_name("theme3.ogg"),
];
asset_music_list
.iter()
.map(|path| asset_server.load::<AudioSource>(path))
.collect::<Vec<Handle<AudioSource>>>()
}
};

commands.insert_resource(MusicHandles(music_handles));
}

fn load_sound_effect_files(mut commands: Commands, asset_server: Res<AssetServer>) {
let sound_effects_folder_handle = asset_server.load_folder(ASSET_FOLDER_SFX);
commands.insert_resource(SoundEffectFolderHandle(sound_effects_folder_handle));
let sound_effect_handles = {
#[cfg(not(target_family = "wasm"))]
{
asset_server.load_folder(ASSET_FOLDER_SFX)
}

#[cfg(target_family = "wasm")]
{
let asset_sfx_list = [
format_sfx_file_name("breathend.ogg"),
format_sfx_file_name("breathloop.ogg"),
format_sfx_file_name("breathstart.ogg"),
];
asset_sfx_list
.iter()
.map(|path| asset_server.load::<AudioSource>(path))
.collect::<Vec<Handle<AudioSource>>>()
}
};

commands.insert_resource(SoundEffectHandles(sound_effect_handles));
}

fn update_music_assets_load_state(
mut audio_load_states: ResMut<AudioLoadStates>,
music_folder_handle: Res<MusicFolderHandle>,
music_handles: Res<MusicHandles>,
asset_server: Res<AssetServer>,
) {
audio_load_states.music_load_state =
asset_server.recursive_dependency_load_state(music_folder_handle.id());
audio_load_states.music_load_state = {
#[cfg(not(target_family = "wasm"))]
{
asset_server
.recursive_dependency_load_state(music_handles.id())
.into()
}
#[cfg(target_family = "wasm")]
{
let all_loaded = music_handles.iter().all(|handle| {
asset_server.recursive_dependency_load_state(handle.id())
== RecursiveDependencyLoadState::Loaded
});
if all_loaded {
RecursiveDependencyLoadState::Loaded.into()
} else {
RecursiveDependencyLoadState::NotLoaded.into()
}
}
};
}

fn update_sound_effect_assets_load_state(
mut audio_load_states: ResMut<AudioLoadStates>,
sound_effect_folder_handle: Res<SoundEffectFolderHandle>,
sound_effect_handles: Res<SoundEffectHandles>,
asset_server: Res<AssetServer>,
) {
audio_load_states.sound_effects_load_state =
asset_server.recursive_dependency_load_state(sound_effect_folder_handle.id());
audio_load_states.sound_effects_load_state = {
#[cfg(not(target_family = "wasm"))]
{
asset_server
.recursive_dependency_load_state(sound_effect_handles.id())
.into()
}
#[cfg(target_family = "wasm")]
{
let all_loaded = sound_effect_handles.iter().all(|handle| {
asset_server.recursive_dependency_load_state(handle.id())
== RecursiveDependencyLoadState::Loaded
});
if all_loaded {
RecursiveDependencyLoadState::Loaded.into()
} else {
RecursiveDependencyLoadState::NotLoaded.into()
}
}
};
}

pub fn audio_assets_loaded() -> impl Condition<()> {
IntoSystem::into_system(resource_equals(AudioLoadStates::LOADED))
}

fn format_music_file_name(file_name: &str) -> String {
format!("{ASSET_FOLDER_MUSIC}/{file_name}")
}

fn format_sfx_file_name(file_name: &str) -> String {
format!("{ASSET_FOLDER_SFX}/{file_name}")
}
75 changes: 64 additions & 11 deletions src/fonts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub struct FontsPlugin;
impl Plugin for FontsPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<FontsLoadState>();
app.init_resource::<FontsFolderHandle>();
app.init_resource::<FontHandles>();
app.add_systems(Startup, load_fonts);
app.add_systems(
Update,
Expand All @@ -20,34 +20,87 @@ impl Plugin for FontsPlugin {
}

#[derive(Resource, PartialEq)]
struct FontsLoadState(RecursiveDependencyLoadState);
enum FontsLoadState {
NotLoaded,
Loading,
Loaded,
Failed,
}

impl Default for FontsLoadState {
fn default() -> Self {
Self(RecursiveDependencyLoadState::NotLoaded)
Self::NotLoaded
}
}

impl FontsLoadState {
pub const LOADED: Self = Self(RecursiveDependencyLoadState::Loaded);
impl From<RecursiveDependencyLoadState> for FontsLoadState {
fn from(value: RecursiveDependencyLoadState) -> Self {
match value {
RecursiveDependencyLoadState::NotLoaded => Self::NotLoaded,
RecursiveDependencyLoadState::Loading => Self::Loading,
RecursiveDependencyLoadState::Loaded => Self::Loaded,
RecursiveDependencyLoadState::Failed => Self::Failed,
}
}
}

#[derive(Resource, Default, Deref, DerefMut)]
struct FontsFolderHandle(Handle<LoadedFolder>);
struct FontHandles(
#[cfg(not(target_family = "wasm"))] Handle<LoadedFolder>,
#[cfg(target_family = "wasm")] Vec<Handle<Font>>,
);

fn load_fonts(mut commands: Commands, asset_server: Res<AssetServer>) {
let fonts_folder_handle = asset_server.load_folder(ASSET_FOLDER_FONTS);
commands.insert_resource(FontsFolderHandle(fonts_folder_handle));
let font_handles = {
#[cfg(not(target_family = "wasm"))]
{
asset_server.load_folder(ASSET_FOLDER_FONTS)
}

#[cfg(target_family = "wasm")]
{
let asset_font_list = [
format!("{ASSET_FOLDER_FONTS}/MorrisRoman-Black.ttf"),
format!("{ASSET_FOLDER_FONTS}/MorrisRomanAlternate-Black.ttf"),
format!("{ASSET_FOLDER_FONTS}/Prince Valiant.ttf"),
];
asset_font_list
.iter()
.map(|path| asset_server.load::<Font>(path))
.collect::<Vec<Handle<Font>>>()
}
};

commands.insert_resource(FontHandles(font_handles));
}

fn update_font_assets_load_state(
mut fonts_load_state: ResMut<FontsLoadState>,
fonts_folder_handle: Res<FontsFolderHandle>,
font_handles: Res<FontHandles>,
asset_server: Res<AssetServer>,
) {
fonts_load_state.0 = asset_server.recursive_dependency_load_state(fonts_folder_handle.id());
*fonts_load_state = {
#[cfg(not(target_family = "wasm"))]
{
asset_server
.recursive_dependency_load_state(font_handles.id())
.into()
}
#[cfg(target_family = "wasm")]
{
let all_loaded = font_handles.iter().all(|handle| {
asset_server.recursive_dependency_load_state(handle.id())
== RecursiveDependencyLoadState::Loaded
});
if all_loaded {
RecursiveDependencyLoadState::Loaded.into()
} else {
RecursiveDependencyLoadState::NotLoaded.into()
}
}
};
}

pub fn font_assets_loaded() -> impl Condition<()> {
IntoSystem::into_system(resource_equals(FontsLoadState::LOADED))
IntoSystem::into_system(resource_equals(FontsLoadState::Loaded))
}
Loading