nightshade-api 0.56.0

Procedural high level API for the nightshade game engine
Documentation
//! Loading sounds and driving the mixer: looping ambience, a spatial emitter,
//! music on its own bus, crossfades, voice ducking, and one-shot UI clicks.

use nightshade_api::prelude::*;

struct Garden {
    emitter: Entity,
    step: Entity,
    music_space: Entity,
    music_drive: Entity,
    ambient: Entity,
    button: Entity,
    hud: Entity,
    on_drive: bool,
}

fn main() {
    run(setup, update).unwrap();
}

fn setup(world: &mut World) -> Garden {
    set_window_title(world, "Audio Garden");
    spawn_floor(world, 12.0);

    let sounds: [(&str, &[u8]); 6] = [
        (
            "music_space",
            include_bytes!("../../../assets/sounds/music_space.ogg"),
        ),
        (
            "music_drive",
            include_bytes!("../../../assets/sounds/music_drive.ogg"),
        ),
        (
            "ambient_water",
            include_bytes!("../../../assets/sounds/ambient_water.ogg"),
        ),
        (
            "sfx_step",
            include_bytes!("../../../assets/sounds/sfx_step.ogg"),
        ),
        (
            "ui_click",
            include_bytes!("../../../assets/sounds/ui_click.ogg"),
        ),
        (
            "voice_speak",
            include_bytes!("../../../assets/sounds/voice_speak.ogg"),
        ),
    ];
    for (name, bytes) in sounds {
        load_sound(world, name, bytes);
    }

    let emitter = spawn_sphere(world, vec3(6.0, 1.0, 0.0));
    set_scale(world, emitter, vec3(0.5, 0.5, 0.5));
    set_color(world, emitter, TEAL);
    set_emissive(world, emitter, [0.1, 0.6, 0.7], 1.5);

    let step = play_sound_at(world, "sfx_step", vec3(6.0, 1.0, 0.0));
    set_spatial_distance(world, step, 2.0, 14.0);

    let ambient = play_sound_looping(world, "ambient_water");
    set_volume(world, ambient, 0.6);

    set_bus_volume(world, AudioBus::Music, -6.0, 0.0);
    let music_space = play_sound_looping(world, "music_space");
    set_pitch(world, music_space, 1.0);
    let music_drive = play_sound_looping(world, "music_drive");
    set_volume(world, music_drive, 0.0);

    let panel = spawn_panel(world, ScreenAnchor::TopRight, 200.0, 64.0);
    let button = panel_button(world, panel, "Click");

    let hud = spawn_text(
        world,
        "C crossfade  V voice  F fade  P/R pause  X stop",
        ScreenAnchor::BottomLeft,
    );

    Garden {
        emitter,
        step,
        music_space,
        music_drive,
        ambient,
        button,
        hud,
        on_drive: false,
    }
}

fn update(world: &mut World, garden: &mut Garden) {
    let angle = elapsed_seconds(world) * 0.7;
    let position = vec3(angle.cos() * 6.0, 1.0, angle.sin() * 6.0);
    set_position(world, garden.emitter, position);
    set_position(world, garden.step, position);

    if button_clicked(world, garden.button) {
        play_sound(world, "ui_click");
    }
    if key_pressed(world, KeyCode::KeyC) {
        garden.on_drive = !garden.on_drive;
        if garden.on_drive {
            crossfade(world, garden.music_space, garden.music_drive, 0.8, 1.5);
            set_text(world, garden.hud, "now playing: music_drive");
        } else {
            crossfade(world, garden.music_drive, garden.music_space, 0.8, 1.5);
            set_text(world, garden.hud, "now playing: music_space");
        }
    }
    if key_pressed(world, KeyCode::KeyV) {
        play_sound(world, "voice_speak");
        duck_voice(world, 0.7, 0.25);
    }
    if key_pressed(world, KeyCode::KeyF) {
        fade_volume(world, garden.ambient, 0.1, 1.0);
    }
    if key_pressed(world, KeyCode::KeyP) {
        pause_sound(world, garden.ambient);
    }
    if key_pressed(world, KeyCode::KeyR) {
        resume_sound(world, garden.ambient);
    }
    if key_pressed(world, KeyCode::KeyX) {
        stop_sound(world, garden.step);
    }
}