Skip to content

Instantly share code, notes, and snippets.

@17cupsofcoffee
Created December 9, 2019 21:56
Show Gist options
  • Save 17cupsofcoffee/f5082a13626ddf0030075d542262c728 to your computer and use it in GitHub Desktop.
Save 17cupsofcoffee/f5082a13626ddf0030075d542262c728 to your computer and use it in GitHub Desktop.
Pooling sound effects in Tetra

Here's a quick example of how you can pool instances of a sound effect in Tetra! There's a few advantages to doing this:

  • You cap the number of identical sounds that can play at once, which avoids you accidentally calling play in a loop and blowing out your speakers (not speaking from experience, honest 😅).
  • It gives you a central place to apply variations to the sound - e.g. you could make it so the pitch gets set to a slightly randomized value each time.
  • It's probably slightly more performant than spawning new SoundInstances every time (as always, avoid premature optimization).
use tetra::audio::{self, Sound, SoundInstance};
use tetra::input::{self, Key};
use tetra::{Context, ContextBuilder, State};
struct SoundPool {
// This isn't used, but you could hold onto it in case you want
// to resize your pool later?
sound: Sound,
instances: Vec<SoundInstance>,
next: usize,
}
impl SoundPool {
fn new(ctx: &Context, sound: Sound, instance_count: usize) -> tetra::Result<SoundPool> {
let mut instances = Vec::with_capacity(instance_count);
for _ in 0..instance_count {
instances.push(sound.spawn(ctx)?);
}
Ok(SoundPool {
sound,
instances,
next: 0,
})
}
fn play(&mut self) {
let instance = &self.instances[self.next];
// If we've looped back to an instance before it stops playing,
// rewind it and play again.
instance.stop();
instance.play();
self.next = (self.next + 1) % self.instances.len();
}
}
struct GameState {
pool: SoundPool,
}
impl GameState {
fn new(ctx: &mut Context) -> tetra::Result<GameState> {
audio::set_master_volume(ctx, 0.4);
let sound = Sound::new("./examples/resources/powerup.wav")?;
let pool = SoundPool::new(ctx, sound, 3)?;
Ok(GameState { pool })
}
}
impl State for GameState {
fn update(&mut self, ctx: &mut Context) -> tetra::Result {
if input::is_key_pressed(ctx, Key::Space) {
self.pool.play();
}
Ok(())
}
}
fn main() -> tetra::Result {
ContextBuilder::new("Pooling Sounds", 640, 480)
.build()?
.run(GameState::new)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment