Skip to main content

phichain-assets

The phichain-assets crate manages game assets including note sprites, line textures, hit effects, and audio resources for the Phichain game engine.

Installation

Add this to your Cargo.toml:
[dependencies]
phichain-assets = "1.0.0-beta.5"
bevy = "0.16.1"

Dependencies

The crate depends on:
  • bevy 0.16.1 (for asset loading and management)
  • bevy_asset_loader 0.23.0-rc.4 (for declarative asset loading)
  • bevy_kira_audio 0.23.0 (for audio assets)
  • bevy_egui 0.35.1 (optional, for editor integration)

Core Plugin

AssetsPlugin
struct
The main asset management plugin.
use bevy::prelude::*;
use phichain_assets::AssetsPlugin;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(AssetsPlugin)
        .run();
}

Asset Collections

ImageAssets

ImageAssets
struct
Collection of all image assets used in the game.
use phichain_assets::ImageAssets;
use bevy::prelude::*;

fn spawn_note(
    mut commands: Commands,
    image_assets: Res<ImageAssets>,
) {
    // Spawn a tap note sprite
    commands.spawn(Sprite::from_image(image_assets.tap.clone()));
}
Note Sprites:
  • tap - Tap note image
  • drag - Drag note image
  • hold - Hold note body image
  • hold_head - Hold note head image
  • hold_tail - Hold note tail image
  • flick - Flick note image
Highlighted Variants:
  • tap_highlight - Highlighted tap note
  • drag_highlight - Highlighted drag note
  • hold_highlight - Highlighted hold body
  • hold_head_highlight - Highlighted hold head
  • flick_highlight - Highlighted flick note
Effects:
  • line - Judgment line texture
  • hit - Hit effect sprite

AudioAssets

AudioAssets
struct
Collection of audio assets for hit sounds and effects.
use phichain_assets::AudioAssets;
use bevy::prelude::*;
use bevy_kira_audio::prelude::*;

fn play_hit_sound(
    audio: Res<Audio>,
    audio_assets: Res<AudioAssets>,
) {
    audio.play(audio_assets.click.clone());
}
  • click - Click/tap sound effect (OGG format)
  • drag - Drag sound effect (OGG format)
  • flick - Flick sound effect (OGG format)
  • metronome - Metronome tick sound (WAV format)

Asset Setup

setup_assets
function
Configure the Bevy asset root directory.This function sets the BEVY_ASSET_ROOT environment variable:
  • In debug builds: Uses the project root directory
  • In release builds: Uses the executable’s parent directory
  • Can be overridden with PHICHAIN_ASSET_ROOT environment variable
use phichain_assets::setup_assets;
use bevy::prelude::*;

fn main() {
    // Call before creating the App
    setup_assets();
    
    App::new()
        .add_plugins(DefaultPlugins)
        .run();
}

Asset Directory Structure

Assets should be organized in the following structure:
project_root/
├── assets/
│   ├── image/
│   │   ├── tap.png
│   │   ├── drag.png
│   │   ├── hold.png
│   │   ├── hold_head.png
│   │   ├── hold_tail.png
│   │   ├── flick.png
│   │   ├── tap.highlight.png
│   │   ├── drag.highlight.png
│   │   ├── hold.highlight.png
│   │   ├── hold_head.highlight.png
│   │   ├── flick.highlight.png
│   │   ├── line.png
│   │   └── hit.png
│   └── audio/
│       ├── click.ogg
│       ├── drag.ogg
│       ├── flick.ogg
│       └── metronome.wav
└── Cargo.toml

Complete Examples

use bevy::prelude::*;
use phichain_assets::{setup_assets, AssetsPlugin, ImageAssets, AudioAssets};
use bevy_kira_audio::prelude::*;

fn main() {
    // Setup asset paths
    setup_assets();
    
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(AudioPlugin)
        .add_plugins(AssetsPlugin)
        .add_systems(Startup, spawn_sprites)
        .add_systems(Update, play_sounds)
        .run();
}

fn spawn_sprites(
    mut commands: Commands,
    image_assets: Res<ImageAssets>,
) {
    commands.spawn(Camera2d);
    
    // Spawn different note types
    commands.spawn((
        Sprite::from_image(image_assets.tap.clone()),
        Transform::from_xyz(-100.0, 0.0, 0.0),
    ));
    
    commands.spawn((
        Sprite::from_image(image_assets.drag.clone()),
        Transform::from_xyz(0.0, 0.0, 0.0),
    ));
    
    commands.spawn((
        Sprite::from_image(image_assets.flick.clone()),
        Transform::from_xyz(100.0, 0.0, 0.0),
    ));
}

fn play_sounds(
    audio: Res<Audio>,
    audio_assets: Res<AudioAssets>,
    keyboard: Res<ButtonInput<KeyCode>>,
) {
    if keyboard.just_pressed(KeyCode::Digit1) {
        audio.play(audio_assets.click.clone());
    }
    if keyboard.just_pressed(KeyCode::Digit2) {
        audio.play(audio_assets.drag.clone());
    }
    if keyboard.just_pressed(KeyCode::Digit3) {
        audio.play(audio_assets.flick.clone());
    }
}

Egui Integration

When using the egui feature, assets are automatically loaded into egui contexts:
[dependencies]
phichain-assets = { version = "1.0.0-beta.5", features = ["egui"] }
bevy_egui = "0.35.1"
use bevy::prelude::*;
use bevy_egui::{EguiContexts, EguiPlugin};
use phichain_assets::{setup_assets, AssetsPlugin, ImageAssets};

fn main() {
    setup_assets();
    
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(EguiPlugin)
        .add_plugins(AssetsPlugin)
        .add_systems(Update, show_assets_in_egui)
        .run();
}

fn show_assets_in_egui(
    mut contexts: EguiContexts,
    image_assets: Res<ImageAssets>,
) {
    egui::Window::new("Assets").show(contexts.ctx_mut(), |ui| {
        ui.label("Note sprites loaded");
        // Assets are automatically available in egui
    });
}

Asset Loading States

Assets are loaded asynchronously. Check if assets are ready:
use bevy::prelude::*;
use phichain_assets::{ImageAssets, AudioAssets};

fn check_assets_loaded(
    image_assets: Option<Res<ImageAssets>>,
    audio_assets: Option<Res<AudioAssets>>,
) {
    match (image_assets, audio_assets) {
        (Some(_), Some(_)) => {
            println!("All assets loaded and ready!");
        }
        (None, _) => {
            println!("Waiting for image assets...");
        }
        (_, None) => {
            println!("Waiting for audio assets...");
        }
    }
}

Custom Assets

Extend the asset system with custom resources:
use bevy::prelude::*;
use bevy_asset_loader::prelude::*;

#[derive(AssetCollection, Resource)]
pub struct CustomAssets {
    #[asset(path = "textures/background.png")]
    pub background: Handle<Image>,
    
    #[asset(path = "fonts/custom.ttf")]
    pub font: Handle<Font>,
}

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .init_collection::<CustomAssets>()
        .run();
}

Troubleshooting

  1. Ensure setup_assets() is called before creating the App
  2. Verify the assets/ directory exists in the correct location
  3. Check file names match exactly (case-sensitive)
  4. Verify image formats are supported (PNG recommended)
  5. Check console for asset loading errors
Set the PHICHAIN_ASSET_ROOT environment variable:
use std::env;

// Set before calling setup_assets()
env::set_var("PHICHAIN_ASSET_ROOT", "/custom/path");
phichain_assets::setup_assets();

See Also