mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 16:21:33 +11:00
commit
241e8b369e
|
@ -4,7 +4,7 @@
|
|||
use agb::fixnum::Num;
|
||||
use agb::input::{Button, ButtonController, Tri};
|
||||
use agb::sound::mixer::SoundChannel;
|
||||
use agb::{include_wav, Gba, fixnum::num};
|
||||
use agb::{fixnum::num, include_wav, Gba};
|
||||
|
||||
// Music - "Dead Code" by Josh Woodward, free download at http://joshwoodward.com
|
||||
const DEAD_CODE: &[u8] = include_wav!("examples/JoshWoodward-DeadCode.wav");
|
||||
|
|
BIN
agb/examples/sfx/jump.wav
Normal file
BIN
agb/examples/sfx/jump.wav
Normal file
Binary file not shown.
BIN
agb/examples/sfx/my_bgm.wav
Normal file
BIN
agb/examples/sfx/my_bgm.wav
Normal file
Binary file not shown.
|
@ -20,9 +20,38 @@ use crate::{
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// let backdrop = InfiniteScrolledMap::new(
|
||||
/// background.background(Priority::P2, RegularBackgroundSize::Background32x32),
|
||||
/// ```rust,no_run
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// extern crate alloc;
|
||||
///
|
||||
/// use alloc::boxed::Box;
|
||||
///
|
||||
/// use agb::display::tiled::{
|
||||
/// InfiniteScrolledMap,
|
||||
/// TileSetting,
|
||||
/// RegularBackgroundSize,
|
||||
/// TileSet,
|
||||
/// TileFormat,
|
||||
/// };
|
||||
/// use agb::display::Priority;
|
||||
///
|
||||
/// mod tilemap {
|
||||
/// pub const BACKGROUND_MAP: &[u16] = &[ // Probably load this from a file
|
||||
/// # 0, 1, 2];
|
||||
/// pub const WIDTH: i32 = // set it to some width
|
||||
/// # 12;
|
||||
/// pub const MAP_TILES: &[u8] = &[ // probably load this from a file
|
||||
/// # 0];
|
||||
/// }
|
||||
///
|
||||
/// # fn foo(mut gba: agb::Gba) {
|
||||
/// let (gfx, mut vram) = gba.display.video.tiled0();
|
||||
///
|
||||
/// let tileset = TileSet::new(&tilemap::MAP_TILES, TileFormat::FourBpp);
|
||||
///
|
||||
/// let mut backdrop = InfiniteScrolledMap::new(
|
||||
/// gfx.background(Priority::P2, RegularBackgroundSize::Background32x32),
|
||||
/// Box::new(|pos| {
|
||||
/// (
|
||||
/// &tileset,
|
||||
|
@ -40,6 +69,7 @@ use crate::{
|
|||
/// backdrop.set_pos(&mut vram, (3, 5).into());
|
||||
/// backdrop.commit(&mut vram);
|
||||
/// backdrop.show();
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct InfiniteScrolledMap<'a> {
|
||||
map: MapLoan<'a, RegularMap>,
|
||||
|
@ -83,11 +113,57 @@ impl<'a> InfiniteScrolledMap<'a> {
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// background.init(&mut vram, start_position, || {
|
||||
/// ```rust,no_run
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// # extern crate alloc;
|
||||
/// #
|
||||
/// # use alloc::boxed::Box;
|
||||
/// #
|
||||
/// # use agb::display::tiled::{
|
||||
/// # InfiniteScrolledMap,
|
||||
/// # TileSetting,
|
||||
/// # RegularBackgroundSize,
|
||||
/// # TileSet,
|
||||
/// # TileFormat,
|
||||
/// # };
|
||||
/// # use agb::display::Priority;
|
||||
/// #
|
||||
/// # mod tilemap {
|
||||
/// # pub const BACKGROUND_MAP: &[u16] = &[0, 1, 2];
|
||||
/// # pub const WIDTH: i32 = 12;
|
||||
/// # pub const MAP_TILES: &[u8] = &[0];
|
||||
/// # }
|
||||
/// #
|
||||
/// # fn foo(mut gba: agb::Gba) {
|
||||
/// # let (gfx, mut vram) = gba.display.video.tiled0();
|
||||
/// #
|
||||
/// # let tileset = TileSet::new(&tilemap::MAP_TILES, TileFormat::FourBpp);
|
||||
/// #
|
||||
/// # let mut backdrop = InfiniteScrolledMap::new(
|
||||
/// # gfx.background(Priority::P2, RegularBackgroundSize::Background32x32),
|
||||
/// # Box::new(|pos| {
|
||||
/// # (
|
||||
/// # &tileset,
|
||||
/// # TileSetting::from_raw(
|
||||
/// # *tilemap::BACKGROUND_MAP
|
||||
/// # .get((pos.x + tilemap::WIDTH * pos.y) as usize)
|
||||
/// # .unwrap_or(&0),
|
||||
/// # ),
|
||||
/// # )
|
||||
/// # }),
|
||||
/// # );
|
||||
/// #
|
||||
/// # let vblank = agb::interrupt::VBlank::get();
|
||||
/// # let mut mixer = gba.mixer.mixer();
|
||||
/// let start_position = agb::fixnum::Vector2D::new(10, 10);
|
||||
/// backdrop.init(&mut vram, start_position, &mut || {
|
||||
/// vblank.wait_for_vblank();
|
||||
/// mixer.frame();
|
||||
/// });
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn init(
|
||||
&mut self,
|
||||
|
@ -111,11 +187,58 @@ impl<'a> InfiniteScrolledMap<'a> {
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// while background.init_partial(&mut vram, start_position) == PartialUpdateStatus::Continue {
|
||||
/// ```rust,no_run
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// # extern crate alloc;
|
||||
/// #
|
||||
/// # use alloc::boxed::Box;
|
||||
/// #
|
||||
/// # use agb::display::tiled::{
|
||||
/// # InfiniteScrolledMap,
|
||||
/// # TileSetting,
|
||||
/// # RegularBackgroundSize,
|
||||
/// # TileSet,
|
||||
/// # TileFormat,
|
||||
/// # PartialUpdateStatus,
|
||||
/// # };
|
||||
/// # use agb::display::Priority;
|
||||
/// #
|
||||
/// # mod tilemap {
|
||||
/// # pub const BACKGROUND_MAP: &[u16] = &[0, 1, 2];
|
||||
/// # pub const WIDTH: i32 = 12;
|
||||
/// # pub const MAP_TILES: &[u8] = &[0];
|
||||
/// # }
|
||||
/// #
|
||||
/// # fn foo(mut gba: agb::Gba) {
|
||||
/// # let (gfx, mut vram) = gba.display.video.tiled0();
|
||||
/// #
|
||||
/// # let tileset = TileSet::new(&tilemap::MAP_TILES, TileFormat::FourBpp);
|
||||
/// #
|
||||
/// # let mut backdrop = InfiniteScrolledMap::new(
|
||||
/// # gfx.background(Priority::P2, RegularBackgroundSize::Background32x32),
|
||||
/// # Box::new(|pos| {
|
||||
/// # (
|
||||
/// # &tileset,
|
||||
/// # TileSetting::from_raw(
|
||||
/// # *tilemap::BACKGROUND_MAP
|
||||
/// # .get((pos.x + tilemap::WIDTH * pos.y) as usize)
|
||||
/// # .unwrap_or(&0),
|
||||
/// # ),
|
||||
/// # )
|
||||
/// # }),
|
||||
/// # );
|
||||
/// #
|
||||
/// # let vblank = agb::interrupt::VBlank::get();
|
||||
/// # let mut mixer = gba.mixer.mixer();
|
||||
/// let start_position = agb::fixnum::Vector2D::new(10, 10);
|
||||
/// while backdrop.init_partial(&mut vram, start_position) == PartialUpdateStatus::Continue {
|
||||
/// vblank.wait_for_vblank();
|
||||
/// mixer.frame();
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn init_partial(
|
||||
&mut self,
|
||||
|
|
|
@ -235,10 +235,17 @@ fn interrupt_to_root(interrupt: Interrupt) -> &'static InterruptRoot {
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let _a = add_interrupt_handler(Interrupt::VBlank, |_: &CriticalSection| {
|
||||
/// println!("Woah there! There's been a vblank!");
|
||||
/// ```rust,no_run
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// use bare_metal::CriticalSection;
|
||||
///
|
||||
/// # fn foo() {
|
||||
/// # use agb::interrupt::{add_interrupt_handler, Interrupt};
|
||||
/// let _a = add_interrupt_handler(Interrupt::VBlank, |_: CriticalSection| {
|
||||
/// agb::println!("Woah there! There's been a vblank!");
|
||||
/// });
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn add_interrupt_handler<'a>(
|
||||
interrupt: Interrupt,
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
///
|
||||
/// This will generate something along the lines of the following:
|
||||
///
|
||||
/// ```
|
||||
/// ```rust,ignore
|
||||
/// // module name comes from the name of the toml file, so `sprites` in this case because it is
|
||||
/// // called `sprites.toml`
|
||||
/// mod sprites {
|
||||
|
@ -75,7 +75,7 @@
|
|||
/// ```
|
||||
///
|
||||
/// In `src/main.rs`
|
||||
/// ```
|
||||
/// ```rust,ignore
|
||||
/// mod gfx {
|
||||
/// use agb::display::object::ObjectControl;
|
||||
///
|
||||
|
@ -105,7 +105,7 @@
|
|||
/// ```
|
||||
///
|
||||
/// In `src/main.rs`:
|
||||
/// ```
|
||||
/// ```rust,ignore
|
||||
/// mod gfx {
|
||||
/// use agb::display::background::BackgroundDistributor;
|
||||
///
|
||||
|
@ -139,7 +139,7 @@ macro_rules! include_font {
|
|||
/// Doing this will ensure that `agb` can correctly set up the environment to call your rust function on start up.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// ```no_run,rust
|
||||
/// #![no_std]
|
||||
/// #![no_main]
|
||||
///
|
||||
|
@ -206,7 +206,7 @@ static mut GBASINGLE: single::Singleton<Gba> = single::Singleton::new(unsafe { G
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// ```no_run,rust
|
||||
/// #![no_std]
|
||||
/// #![no_main]
|
||||
///
|
||||
|
|
|
@ -35,9 +35,13 @@
|
|||
//! To create a sound mixer, you will need to get it out of the [`Gba`](crate::Gba) struct
|
||||
//! as follows:
|
||||
//!
|
||||
//! ```
|
||||
//! ```rust,no_run
|
||||
//! # #![no_std]
|
||||
//! # #![no_main]
|
||||
//! # fn foo(gba: &mut agb::Gba) {
|
||||
//! let mut mixer = gba.mixer.mixer();
|
||||
//! mixer.enable();
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Doing the per-frame work
|
||||
|
@ -48,22 +52,34 @@
|
|||
//!
|
||||
//! Without interrupts:
|
||||
//!
|
||||
//! ```
|
||||
//! ```rust,no_run
|
||||
//! # #![no_std]
|
||||
//! # #![no_main]
|
||||
//! # fn foo(gba: &mut agb::Gba) {
|
||||
//! # let mut mixer = gba.mixer.mixer();
|
||||
//! # let vblank = agb::interrupt::VBlank::get();
|
||||
//! // Somewhere in your main loop:
|
||||
//! mixer.frame();
|
||||
//! vblank.wait_for_vblank();
|
||||
//! mixer.after_vblank();
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! Or with interrupts:
|
||||
//!
|
||||
//! ```
|
||||
//! ```rust,no_run
|
||||
//! # #![no_std]
|
||||
//! # #![no_main]
|
||||
//! # fn foo(gba: &mut agb::Gba) {
|
||||
//! # let mut mixer = gba.mixer.mixer();
|
||||
//! # let vblank = agb::interrupt::VBlank::get();
|
||||
//! // outside your main loop, close to initialisation
|
||||
//! let _mixer_interrupt = mixer.setup_interrupt_handler();
|
||||
//!
|
||||
//! // inside your main loop
|
||||
//! mixer.frame();
|
||||
//! vblank.wait_for_vblank();
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! Despite being high performance, the mixer still takes a sizable portion of CPU time (6-10%
|
||||
|
@ -79,14 +95,21 @@
|
|||
//! Use the [`include_wav!`](crate::include_wav) macro in order to load the sound. This will produce
|
||||
//! an error if your wav file is of the wrong frequency.
|
||||
//!
|
||||
//! ```
|
||||
//! ```rust,no_run
|
||||
//! # #![no_std]
|
||||
//! # #![no_main]
|
||||
//! # fn foo(gba: &mut agb::Gba) {
|
||||
//! # let mut mixer = gba.mixer.mixer();
|
||||
//! # let vblank = agb::interrupt::VBlank::get();
|
||||
//! # use agb::{*, sound::mixer::*};
|
||||
//! // Outside your main function in global scope:
|
||||
//! const MY_CRAZY_SOUND: &[u8] = include_wav!("sfx/my_crazy_sound.wav");
|
||||
//! const MY_CRAZY_SOUND: &[u8] = include_wav!("examples/sfx/jump.wav");
|
||||
//!
|
||||
//! // Then to play the sound:
|
||||
//! let mut channel = SoundChannel::new(MY_CRAZY_SOUND);
|
||||
//! channel.stereo();
|
||||
//! let _ = mixer.play_sound(channel); // we don't mind if this sound doesn't actually play
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! See the [`SoundChannel`] struct for more details on how you can configure the sounds to play.
|
||||
|
@ -152,25 +175,39 @@ enum SoundPriority {
|
|||
/// play regardless of whether you have lots of sound effects playing. You create a high
|
||||
/// priority sound channel using [`new_high_priority`](SoundChannel::new_high_priority).
|
||||
///
|
||||
/// ```
|
||||
/// ```rust,no_run
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// # use agb::sound::mixer::*;
|
||||
/// # use agb::*;
|
||||
/// // in global scope:
|
||||
/// const MY_BGM: [u8] = include_wav!("sfx/my_bgm.wav");
|
||||
/// const MY_BGM: &[u8] = include_wav!("examples/sfx/my_bgm.wav");
|
||||
///
|
||||
/// // somewhere in code
|
||||
/// # fn foo(gba: &mut Gba) {
|
||||
/// # let mut mixer = gba.mixer.mixer();
|
||||
/// let mut bgm = SoundChannel::new_high_priority(MY_BGM);
|
||||
/// bgm.stereo().should_loop();
|
||||
/// let _ = mixer.play_sound(bgm);
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// ## Playing a sound effect
|
||||
///
|
||||
/// ```
|
||||
/// ```rust,no_run
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// # use agb::sound::mixer::*;
|
||||
/// # use agb::*;
|
||||
/// // in global scope:
|
||||
/// const JUMP_SOUND: [u8] = include_wav!("sfx/jump_sound.wav");
|
||||
/// const JUMP_SOUND: &[u8] = include_wav!("examples/sfx/jump.wav");
|
||||
///
|
||||
/// // somewhere in code
|
||||
/// let jump_sound = SoundChannel::new(MY_JUMP_SOUND);
|
||||
/// # fn foo(gba: &mut Gba) {
|
||||
/// # let mut mixer = gba.mixer.mixer();
|
||||
/// let jump_sound = SoundChannel::new(JUMP_SOUND);
|
||||
/// let _ = mixer.play_sound(jump_sound);
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct SoundChannel {
|
||||
data: &'static [u8],
|
||||
|
@ -198,13 +235,20 @@ impl SoundChannel {
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// ```rust,no_run
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// # use agb::sound::mixer::*;
|
||||
/// # use agb::*;
|
||||
/// # fn foo(gba: &mut Gba) {
|
||||
/// # let mut mixer = gba.mixer.mixer();
|
||||
/// // in global scope:
|
||||
/// const JUMP_SOUND: [u8] = include_wav!("sfx/jump_sound.wav");
|
||||
/// const JUMP_SOUND: &[u8] = include_wav!("examples/sfx/jump.wav");
|
||||
///
|
||||
/// // somewhere in code
|
||||
/// let jump_sound = SoundChannel::new(MY_JUMP_SOUND);
|
||||
/// let jump_sound = SoundChannel::new(JUMP_SOUND);
|
||||
/// let _ = mixer.play_sound(jump_sound);
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
|
@ -233,14 +277,21 @@ impl SoundChannel {
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// ```rust,no_run
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// # use agb::sound::mixer::*;
|
||||
/// # use agb::*;
|
||||
/// # fn foo(gba: &mut Gba) {
|
||||
/// # let mut mixer = gba.mixer.mixer();
|
||||
/// // in global scope:
|
||||
/// const MY_BGM: [u8] = include_wav!("sfx/my_bgm.wav");
|
||||
/// const MY_BGM: &[u8] = include_wav!("examples/sfx/my_bgm.wav");
|
||||
///
|
||||
/// // somewhere in code
|
||||
/// let mut bgm = SoundChannel::new_high_priority(MY_BGM);
|
||||
/// bgm.stereo().should_loop();
|
||||
/// let _ = mixer.play_sound(bgm);
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
|
|
|
@ -36,15 +36,28 @@ extern "C" {
|
|||
/// You should not create this struct directly, instead creating it through the [`Gba`](crate::Gba)
|
||||
/// struct as follows:
|
||||
///
|
||||
/// ```
|
||||
/// ```rust,no_run
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// # use agb::sound::mixer::*;
|
||||
/// # use agb::*;
|
||||
/// # fn foo(gba: &mut Gba) {
|
||||
/// let mut mixer = gba.mixer.mixer();
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// ```rust,no_run
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// # use agb::sound::mixer::*;
|
||||
/// # use agb::*;
|
||||
/// # fn foo(gba: &mut Gba) {
|
||||
/// # let mut mixer = gba.mixer.mixer();
|
||||
/// # let vblank = agb::interrupt::VBlank::get();
|
||||
/// // Outside your main function in global scope:
|
||||
/// const MY_CRAZY_SOUND: &[u8] = include_wav!("sfx/my_crazy_sound.wav");
|
||||
/// const MY_CRAZY_SOUND: &[u8] = include_wav!("examples/sfx/jump.wav");
|
||||
///
|
||||
/// // in your main function:
|
||||
/// let mut mixer = gba.mixer.mixer();
|
||||
|
@ -57,6 +70,7 @@ extern "C" {
|
|||
/// vblank.wait_for_vblank();
|
||||
/// mixer.after_vblank();
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct Mixer {
|
||||
buffer: MixerBuffer,
|
||||
|
@ -72,12 +86,20 @@ pub struct Mixer {
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// ```rust,no_run
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// # use agb::sound::mixer::*;
|
||||
/// # use agb::*;
|
||||
/// # fn foo(gba: &mut Gba) {
|
||||
/// # let mut mixer = gba.mixer.mixer();
|
||||
/// # const MY_BGM: &[u8] = include_wav!("examples/sfx/my_bgm.wav");
|
||||
/// let mut channel = SoundChannel::new_high_priority(MY_BGM);
|
||||
/// let bgm_channel_id = mixer.play_sound(channel).unwrap(); // will always be Some if high priority
|
||||
///
|
||||
/// // Later, stop that particular channel
|
||||
/// mixer.channel(bgm_channel_id).stop();
|
||||
/// mixer.channel(&bgm_channel_id).expect("Expected to still be playing").stop();
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct ChannelId(usize, i32);
|
||||
|
||||
|
@ -106,12 +128,20 @@ impl Mixer {
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// ```rust,no_run
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// # use agb::sound::mixer::*;
|
||||
/// # use agb::*;
|
||||
/// # fn foo(gba: &mut Gba) {
|
||||
/// # let mut mixer = gba.mixer.mixer();
|
||||
/// # let vblank = agb::interrupt::VBlank::get();
|
||||
/// loop {
|
||||
/// mixer.frame();
|
||||
/// vblank.wait_for_vblank();
|
||||
/// mixer.after_vblank();
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
#[cfg(not(feature = "freq32768"))]
|
||||
pub fn after_vblank(&mut self) {
|
||||
|
@ -127,7 +157,14 @@ impl Mixer {
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// ```rust,no_run
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// # use agb::sound::mixer::*;
|
||||
/// # use agb::*;
|
||||
/// # fn foo(gba: &mut Gba) {
|
||||
/// # let mut mixer = gba.mixer.mixer();
|
||||
/// # let vblank = agb::interrupt::VBlank::get();
|
||||
/// // you must set this to a named variable to ensure that the scope is long enough
|
||||
/// let _mixer_interrupt = mixer.setup_interrupt_handler();
|
||||
///
|
||||
|
@ -135,6 +172,7 @@ impl Mixer {
|
|||
/// mixer.frame();
|
||||
/// vblank.wait_for_vblank();
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn setup_interrupt_handler(&self) -> InterruptHandler<'_> {
|
||||
let mut timer1 = unsafe { Timer::new(1) };
|
||||
|
@ -157,12 +195,20 @@ impl Mixer {
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// ```rust,no_run
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// # use agb::sound::mixer::*;
|
||||
/// # use agb::*;
|
||||
/// # fn foo(gba: &mut Gba) {
|
||||
/// # let mut mixer = gba.mixer.mixer();
|
||||
/// # let vblank = agb::interrupt::VBlank::get();
|
||||
/// loop {
|
||||
/// mixer.frame();
|
||||
/// vblank.wait_for_vblank();
|
||||
/// mixer.after_vblank(); // optional, only if not using interrupts
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn frame(&mut self) {
|
||||
if !self.buffer.should_calculate() {
|
||||
|
@ -188,9 +234,17 @@ impl Mixer {
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// ```rust,no_run
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// # use agb::sound::mixer::*;
|
||||
/// # use agb::*;
|
||||
/// # fn foo(gba: &mut Gba) {
|
||||
/// # let mut mixer = gba.mixer.mixer();
|
||||
/// # const MY_BGM: &[u8] = include_wav!("examples/sfx/my_bgm.wav");
|
||||
/// let mut channel = SoundChannel::new_high_priority(MY_BGM);
|
||||
/// let bgm_channel_id = mixer.play_sound(channel).unwrap(); // will always be Some if high priority
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn play_sound(&mut self, new_channel: SoundChannel) -> Option<ChannelId> {
|
||||
for (i, channel) in self.channels.iter_mut().enumerate() {
|
||||
|
@ -229,12 +283,20 @@ impl Mixer {
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// ```rust,no_run
|
||||
/// # #![no_std]
|
||||
/// # #![no_main]
|
||||
/// # use agb::sound::mixer::*;
|
||||
/// # use agb::*;
|
||||
/// # fn foo(gba: &mut Gba) {
|
||||
/// # let mut mixer = gba.mixer.mixer();
|
||||
/// # const MY_BGM: &[u8] = include_wav!("examples/sfx/my_bgm.wav");
|
||||
/// let mut channel = SoundChannel::new_high_priority(MY_BGM);
|
||||
/// let bgm_channel_id = mixer.play_sound(channel).unwrap(); // will always be Some if high priority
|
||||
///
|
||||
/// // Later, stop that particular channel
|
||||
/// mixer.channel(bgm_channel_id).stop();
|
||||
/// mixer.channel(&bgm_channel_id).expect("Expected still to be playing").stop();
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn channel(&mut self, id: &ChannelId) -> Option<&'_ mut SoundChannel> {
|
||||
if let Some(channel) = &mut self.channels[id.0] {
|
||||
|
|
5
justfile
5
justfile
|
@ -17,6 +17,9 @@ test:
|
|||
test-release:
|
||||
just _test-release agb
|
||||
|
||||
doctest-agb:
|
||||
(cd agb && cargo test --doc -Z doctest-xcompile)
|
||||
|
||||
clean:
|
||||
just _all-crates _clean
|
||||
|
||||
|
@ -34,7 +37,7 @@ run-game game:
|
|||
run-game-debug game:
|
||||
(cd "examples/{{game}}" && cargo run)
|
||||
|
||||
ci: build-debug clippy test build-release test-release build-roms build-book
|
||||
ci: build-debug clippy test build-release test-release doctest-agb build-roms build-book
|
||||
|
||||
build-roms:
|
||||
just _build-rom "examples/the-purple-night" "PURPLENIGHT"
|
||||
|
|
Loading…
Reference in a new issue