Back to Amethyst

How to Use Assets

book/src/assets/how_to_use_assets.md

0.15.37.9 KB
Original Source

How to Use Assets

This guide covers the basic usage of assets into Amethyst for existing supported formats. For a list of supported formats, please use this search for "Format" in the API documentation, and filter by the following crates:

  • amethyst_assets
  • amethyst_audio
  • amethyst_gltf
  • amethyst_locale
  • amethyst_ui

Steps

  1. Instantiate the Amethyst application with the assets directory.

    rust
    # extern crate amethyst;
    use amethyst::prelude::*;
    use amethyst::utils::application_root_dir;
    
    pub struct LoadingState;
    impl SimpleState for LoadingState {}
    
    fn main() -> amethyst::Result<()> {
        // Sets up the application to read assets in
        // `<app_dir>/assets`
        let app_root = application_root_dir()?;
        let assets_dir = app_root.join("assets");
    
        let game_data = DispatcherBuilder::default();
    
        let mut game = Application::new(assets_dir, LoadingState, game_data)?;
        //game.run();
        Ok(())
    }
    
  2. Ensure that the AssetProcessorSystem<A> system for asset type A is registered in the dispatcher. You can use register_asset_type! macro for this.

    For asset type A, AssetProcessorSystem<A> is a System that will asynchronously load A assets. Usually the crate that provides A will also register AssetProcessorSystem<A> through a SystemBundle. Examples:

    • FontAsset is provided by amethyst_ui, UiBundle registers AssetProcessorSystem<FontAsset>.
    • Source is provided by amethyst_audio, AudioBundle registers AssetProcessorSystem<Source>.
  3. Use the Loader resource to load the asset.

    rust
    # extern crate amethyst;
    # use amethyst::prelude::*;
    # use amethyst::utils::application_root_dir;
    # use amethyst::{
    #   assets::{AssetStorage, DefaultLoader, Handle, Loader, ProgressCounter},
    #   renderer::{formats::texture::ImageFormat, Texture},
    # };
    # 
    pub struct LoadingState {
        /// Handle to the player texture.
        texture_handle: Option<Handle<Texture>>,
    }
    
    impl SimpleState for LoadingState {
        fn on_start(&mut self, data: StateData<'_, GameData>) {
            let loader = data.resources.get::<DefaultLoader>().unwrap();
            let texture_handle = loader.load("player.png");
    
            self.texture_handle = Some(texture_handle);
        }
    }
    # fn main() -> amethyst::Result<()> {
    #   let app_root = application_root_dir()?;
    #   let assets_dir = app_root.join("assets");
    # 
    #   let game_data = DispatcherBuilder::default();
    #   let mut game = Application::new(
    #       assets_dir,
    #       LoadingState {
    #           texture_handle: None,
    #       },
    #       game_data,
    #   )?;
    # 
    #   //game.run();
    #   Ok(())
    # }
    
  4. Wait for the asset to be loaded.

    When loader.load(..) is used to load an Asset, the method returns immediately with a handle for the asset. The asset loading is handled asynchronously in the background, so if the handle is used to retrieve the asset, such as with resources.get::<AssetStorage<Texture>>().get(texture_handle), it will return None until the Texture has finished loading.

    rust
    # extern crate amethyst;
    # use amethyst::prelude::*;
    # use amethyst::utils::application_root_dir;
    # use amethyst::{
    #   assets::{AssetStorage, DefaultLoader, Handle, Loader, ProgressCounter},
    #   renderer::{formats::texture::ImageFormat, Texture},
    # };
    # 
    # pub struct GameState {
    #   /// Handle to the player texture.
    #   texture_handle: Handle<Texture>,
    # }
    # 
    # impl SimpleState for GameState {}
    # 
    # pub struct LoadingState {
    #   /// Handle to the player texture.
    #   texture_handle: Option<Handle<Texture>>,
    # }
    # 
    impl SimpleState for LoadingState {
        //..
    #   fn on_start(&mut self, data: StateData<'_, GameData>) {
    #       let loader = data.resources.get::<DefaultLoader>().unwrap();
    #       let texture_handle = loader.load("player.png");
    # 
    #       self.texture_handle = Some(texture_handle);
    #   }
    # 
        fn update(&mut self, data: &mut StateData<'_, GameData>) -> SimpleTrans {
            let texture_storage = data.resources.get::<AssetStorage<Texture>>().unwrap();
            if let Some(texture) = texture_storage.get(self.texture_handle.as_ref().unwrap()) {
                println!("Loaded texture: {:?}", texture);
                Trans::Switch(Box::new(GameState {
                    texture_handle: self.texture_handle.take().expect(
                        "Expected `texture_handle` to exist when `progress_counter` is complete.",
                    ),
                }))
            } else {
                Trans::None
            }
        }
    }
    # fn main() -> amethyst::Result<()> {
    #   let app_root = application_root_dir()?;
    #   let assets_dir = app_root.join("assets");
    # 
    #   let game_data = DispatcherBuilder::default();
    #   let mut game = Application::new(
    #       assets_dir,
    #       LoadingState {
    #           texture_handle: None,
    #       },
    #       game_data,
    #   )?;
    # 
    #   //game.run();
    #   Ok(())
    # }
    

    The asset handle can now be used:

    rust
    # extern crate amethyst;
    # use amethyst::prelude::*;
    # use amethyst::utils::application_root_dir;
    # use amethyst::{
    #   assets::{AssetStorage, DefaultLoader, Handle, Loader, ProgressCounter},
    #   renderer::{formats::texture::ImageFormat, Texture},
    # };
    # 
    # pub struct LoadingState {
    #   /// Handle to the player texture.
    #   texture_handle: Option<Handle<Texture>>,
    # }
    # 
    # impl SimpleState for LoadingState {
    #   fn on_start(&mut self, data: StateData<'_, GameData>) {
    #       let loader = data.resources.get::<DefaultLoader>().unwrap();
    #       let texture_handle = loader.load("player.png");
    # 
    #       self.texture_handle = Some(texture_handle);
    #   }
    # 
    #   fn update(&mut self, data: &mut StateData<'_, GameData>) -> SimpleTrans {
    #       let texture_storage = data.resources.get::<AssetStorage<Texture>>().unwrap();
    #       if let Some(texture) = texture_storage.get(self.texture_handle.as_ref().unwrap()) {
    #           println!("Loaded texture: {:?}", texture);
    #           Trans::Switch(Box::new(GameState {
    #               texture_handle: self.texture_handle.take().expect(
    #                   "Expected `texture_handle` to exist when `progress_counter` is complete.",
    #               ),
    #           }))
    #       } else {
    #           Trans::None
    #       }
    #   }
    # }
    # 
    # pub struct GameState {
    #   /// Handle to the player texture.
    #   texture_handle: Handle<Texture>,
    # }
    impl SimpleState for GameState {
        fn on_start(&mut self, data: StateData<'_, GameData>) {
            // Create the player entity.
            data.world.push((self.texture_handle.clone(),));
        }
    }
    # fn main() -> amethyst::Result<()> {
    #   let app_root = application_root_dir()?;
    #   let assets_dir = app_root.join("assets");
    # 
    #   let game_data = DispatcherBuilder::default();
    #   let mut game = Application::new(
    #       assets_dir,
    #       LoadingState {
    #           texture_handle: None,
    #       },
    #       game_data,
    #   )?;
    # 
    #   //game.run();
    #   Ok(())
    # }
    #