mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Add simple collision sound to breakout (#4331)
# Objective - Add sound effect to the breakout example ## Solution - Add a collision event and a system that listens to the event and plays a sound I only added a single sound for all collisions for the sake of simplicity, but this could easily be extended to play a different sound depending on the type of entity hit. The sound was generated randomly by using https://sfxr.me https://sfxr.me/#11111GA9soYREjtsWhzjPrpMDEYSjX8Fo1E6PnKhxdw6tu869XW4EAc3nzpKVAYLMzToNcHQtQjeBqjZukqPmMDToGdYQQCWBnC3nEYfp53se5ep9btxRdLK Closes #4326 https://user-images.githubusercontent.com/8348954/160154727-00e30743-3385-4c2f-97f0-1aaaf9a4dcc5.mp4 For some reason the video has a lot of delay in the sound, but when playing it locally there's no delay --- ## Changelog - Added sound to breakout example - Added bevy_audio and vorbis to the feature list ran for examples in CI ## Migration Guide N/A
This commit is contained in:
parent
e1c2ace1f2
commit
6e5955f162
3 changed files with 31 additions and 4 deletions
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
|
@ -274,13 +274,13 @@ jobs:
|
|||
toolchain: stable
|
||||
- name: Build bevy
|
||||
run: |
|
||||
cargo build --no-default-features --features "bevy_dynamic_plugin,bevy_gilrs,bevy_gltf,bevy_winit,render,png,hdr,x11,bevy_ci_testing,trace,trace_chrome"
|
||||
cargo build --no-default-features --features "bevy_dynamic_plugin,bevy_gilrs,bevy_gltf,bevy_winit,render,png,hdr,x11,bevy_ci_testing,trace,trace_chrome,bevy_audio,vorbis"
|
||||
- name: Run examples
|
||||
run: |
|
||||
for example in .github/example-run/*.ron; do
|
||||
example_name=`basename $example .ron`
|
||||
echo "running $example_name - "`date`
|
||||
time CI_TESTING_CONFIG=$example xvfb-run cargo run --example $example_name --no-default-features --features "bevy_dynamic_plugin,bevy_gilrs,bevy_gltf,bevy_winit,render,png,hdr,x11,bevy_ci_testing,trace,trace_chrome"
|
||||
time CI_TESTING_CONFIG=$example xvfb-run cargo run --example $example_name --no-default-features --features "bevy_dynamic_plugin,bevy_gilrs,bevy_gltf,bevy_winit,render,png,hdr,x11,bevy_ci_testing,trace,trace_chrome,bevy_audio,vorbis"
|
||||
sleep 10
|
||||
done
|
||||
zip traces.zip trace*.json
|
||||
|
|
BIN
assets/sounds/breakout_collision.ogg
Normal file
BIN
assets/sounds/breakout_collision.ogg
Normal file
Binary file not shown.
|
@ -58,12 +58,14 @@ fn main() {
|
|||
.insert_resource(Scoreboard { score: 0 })
|
||||
.insert_resource(ClearColor(BACKGROUND_COLOR))
|
||||
.add_startup_system(setup)
|
||||
.add_event::<CollisionEvent>()
|
||||
.add_system_set(
|
||||
SystemSet::new()
|
||||
.with_run_criteria(FixedTimestep::step(TIME_STEP as f64))
|
||||
.with_system(check_for_collisions)
|
||||
.with_system(move_paddle.before(check_for_collisions))
|
||||
.with_system(apply_velocity.before(check_for_collisions)),
|
||||
.with_system(apply_velocity.before(check_for_collisions))
|
||||
.with_system(play_collision_sound.after(check_for_collisions)),
|
||||
)
|
||||
.add_system(update_scoreboard)
|
||||
.add_system(bevy::input::system::exit_on_esc_system)
|
||||
|
@ -82,9 +84,14 @@ struct Velocity(Vec2);
|
|||
#[derive(Component)]
|
||||
struct Collider;
|
||||
|
||||
#[derive(Default)]
|
||||
struct CollisionEvent;
|
||||
|
||||
#[derive(Component)]
|
||||
struct Brick;
|
||||
|
||||
struct CollisionSound(Handle<AudioSource>);
|
||||
|
||||
// This bundle is a collection of the components that define a "wall" in our game
|
||||
#[derive(Bundle)]
|
||||
struct WallBundle {
|
||||
|
@ -167,6 +174,10 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
commands.spawn_bundle(OrthographicCameraBundle::new_2d());
|
||||
commands.spawn_bundle(UiCameraBundle::default());
|
||||
|
||||
// Sound
|
||||
let ball_collision_sound = asset_server.load("sounds/breakout_collision.ogg");
|
||||
commands.insert_resource(CollisionSound(ball_collision_sound));
|
||||
|
||||
// Paddle
|
||||
let paddle_y = BOTTOM_WALL + GAP_BETWEEN_PADDLE_AND_FLOOR;
|
||||
|
||||
|
@ -268,7 +279,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
|
|||
// the space on the top and sides of the bricks only captures a lower bound, not an exact value
|
||||
let center_of_bricks = (LEFT_WALL + RIGHT_WALL) / 2.0;
|
||||
let left_edge_of_bricks = center_of_bricks
|
||||
// Space taken up by the bricks
|
||||
// Space taken up by the bricks
|
||||
- (n_columns as f32 / 2.0 * BRICK_SIZE.x)
|
||||
// Space taken up by the gaps
|
||||
- n_vertical_gaps as f32 / 2.0 * GAP_BETWEEN_BRICKS;
|
||||
|
@ -349,6 +360,7 @@ fn check_for_collisions(
|
|||
mut scoreboard: ResMut<Scoreboard>,
|
||||
mut ball_query: Query<(&mut Velocity, &Transform), With<Ball>>,
|
||||
collider_query: Query<(Entity, &Transform, Option<&Brick>), With<Collider>>,
|
||||
mut collision_events: EventWriter<CollisionEvent>,
|
||||
) {
|
||||
let (mut ball_velocity, ball_transform) = ball_query.single_mut();
|
||||
let ball_size = ball_transform.scale.truncate();
|
||||
|
@ -362,6 +374,9 @@ fn check_for_collisions(
|
|||
transform.scale.truncate(),
|
||||
);
|
||||
if let Some(collision) = collision {
|
||||
// Sends a collision event so that other systems can react to the collision
|
||||
collision_events.send_default();
|
||||
|
||||
// Bricks should be despawned and increment the scoreboard on collision
|
||||
if maybe_brick.is_some() {
|
||||
scoreboard.score += 1;
|
||||
|
@ -394,3 +409,15 @@ fn check_for_collisions(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn play_collision_sound(
|
||||
mut collision_events: EventReader<CollisionEvent>,
|
||||
audio: Res<Audio>,
|
||||
sound: Res<CollisionSound>,
|
||||
) {
|
||||
// Play a sound once per frame if a collision occurred. `count` consumes the
|
||||
// events, preventing them from triggering a sound on the next frame.
|
||||
if collision_events.iter().count() > 0 {
|
||||
audio.play(sound.0.clone());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue