@@ -58,12 +58,14 @@ fn main() {
58
58
. insert_resource ( Scoreboard { score : 0 } )
59
59
. insert_resource ( ClearColor ( BACKGROUND_COLOR ) )
60
60
. add_startup_system ( setup)
61
+ . add_event :: < CollisionEvent > ( )
61
62
. add_system_set (
62
63
SystemSet :: new ( )
63
64
. with_run_criteria ( FixedTimestep :: step ( TIME_STEP as f64 ) )
64
65
. with_system ( check_for_collisions)
65
66
. with_system ( move_paddle. before ( check_for_collisions) )
66
- . with_system ( apply_velocity. before ( check_for_collisions) ) ,
67
+ . with_system ( apply_velocity. before ( check_for_collisions) )
68
+ . with_system ( play_collision_sound. after ( check_for_collisions) ) ,
67
69
)
68
70
. add_system ( update_scoreboard)
69
71
. add_system ( bevy:: input:: system:: exit_on_esc_system)
@@ -82,9 +84,14 @@ struct Velocity(Vec2);
82
84
#[ derive( Component ) ]
83
85
struct Collider ;
84
86
87
+ #[ derive( Default ) ]
88
+ struct CollisionEvent ;
89
+
85
90
#[ derive( Component ) ]
86
91
struct Brick ;
87
92
93
+ struct CollisionSound ( Handle < AudioSource > ) ;
94
+
88
95
// This bundle is a collection of the components that define a "wall" in our game
89
96
#[ derive( Bundle ) ]
90
97
struct WallBundle {
@@ -167,6 +174,10 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
167
174
commands. spawn_bundle ( OrthographicCameraBundle :: new_2d ( ) ) ;
168
175
commands. spawn_bundle ( UiCameraBundle :: default ( ) ) ;
169
176
177
+ // Sound
178
+ let ball_collision_sound = asset_server. load ( "sounds/breakout_collision.ogg" ) ;
179
+ commands. insert_resource ( CollisionSound ( ball_collision_sound) ) ;
180
+
170
181
// Paddle
171
182
let paddle_y = BOTTOM_WALL + GAP_BETWEEN_PADDLE_AND_FLOOR ;
172
183
@@ -268,7 +279,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
268
279
// the space on the top and sides of the bricks only captures a lower bound, not an exact value
269
280
let center_of_bricks = ( LEFT_WALL + RIGHT_WALL ) / 2.0 ;
270
281
let left_edge_of_bricks = center_of_bricks
271
- // Space taken up by the bricks
282
+ // Space taken up by the bricks
272
283
- ( n_columns as f32 / 2.0 * BRICK_SIZE . x )
273
284
// Space taken up by the gaps
274
285
- n_vertical_gaps as f32 / 2.0 * GAP_BETWEEN_BRICKS ;
@@ -349,6 +360,7 @@ fn check_for_collisions(
349
360
mut scoreboard : ResMut < Scoreboard > ,
350
361
mut ball_query : Query < ( & mut Velocity , & Transform ) , With < Ball > > ,
351
362
collider_query : Query < ( Entity , & Transform , Option < & Brick > ) , With < Collider > > ,
363
+ mut collision_events : EventWriter < CollisionEvent > ,
352
364
) {
353
365
let ( mut ball_velocity, ball_transform) = ball_query. single_mut ( ) ;
354
366
let ball_size = ball_transform. scale . truncate ( ) ;
@@ -362,6 +374,9 @@ fn check_for_collisions(
362
374
transform. scale . truncate ( ) ,
363
375
) ;
364
376
if let Some ( collision) = collision {
377
+ // Sends a collision event so that other systems can react to the collision
378
+ collision_events. send_default ( ) ;
379
+
365
380
// Bricks should be despawned and increment the scoreboard on collision
366
381
if maybe_brick. is_some ( ) {
367
382
scoreboard. score += 1 ;
@@ -394,3 +409,15 @@ fn check_for_collisions(
394
409
}
395
410
}
396
411
}
412
+
413
+ fn play_collision_sound (
414
+ mut collision_events : EventReader < CollisionEvent > ,
415
+ audio : Res < Audio > ,
416
+ sound : Res < CollisionSound > ,
417
+ ) {
418
+ // Play a sound once per frame if a collision occurred. `count` consumes the
419
+ // events, preventing them from triggering a sound on the next frame.
420
+ if collision_events. iter ( ) . count ( ) > 0 {
421
+ audio. play ( sound. 0 . clone ( ) ) ;
422
+ }
423
+ }
0 commit comments