5
5
use bevy:: prelude:: * ;
6
6
7
7
const TEXT_COLOR : Color = Color :: srgb ( 0.9 , 0.9 , 0.9 ) ;
8
+ const VOLUME_MAX : u32 = 9 ;
8
9
9
10
// Enum that will be used as a global state for the game
10
11
#[ derive( Clone , Copy , Default , Eq , PartialEq , Debug , Hash , States ) ]
@@ -27,6 +28,9 @@ enum DisplayQuality {
27
28
#[ derive( Resource , Debug , Component , PartialEq , Eq , Clone , Copy ) ]
28
29
struct Volume ( u32 ) ;
29
30
31
+ #[ derive( Resource , Deref ) ]
32
+ struct MenuMusic ( Handle < AudioSource > ) ;
33
+
30
34
fn main ( ) {
31
35
App :: new ( )
32
36
. add_plugins ( DefaultPlugins )
@@ -36,13 +40,20 @@ fn main() {
36
40
// Declare the game state, whose starting value is determined by the `Default` trait
37
41
. init_state :: < GameState > ( )
38
42
. add_systems ( Startup , setup)
43
+ . add_systems ( Update , translate_discreet_volume_to_global_volume. run_if ( resource_changed :: < Volume > ) )
39
44
// Adds the plugins for each state
40
45
. add_plugins ( ( splash:: splash_plugin, menu:: menu_plugin, game:: game_plugin) )
41
46
. run ( ) ;
42
47
}
43
48
44
- fn setup ( mut commands : Commands ) {
49
+ fn setup (
50
+ mut commands : Commands ,
51
+ asset_server : Res < AssetServer > ,
52
+ ) {
45
53
commands. spawn ( Camera2d ) ;
54
+ // Sound
55
+ let music = asset_server. load ( "sounds/Windless Slopes.ogg" ) ;
56
+ commands. insert_resource ( MenuMusic ( music) ) ;
46
57
}
47
58
48
59
mod splash {
@@ -113,14 +124,16 @@ mod game {
113
124
prelude:: * ,
114
125
} ;
115
126
127
+ use crate :: { play_music, stop_music, MenuMusic } ;
128
+
116
129
use super :: { despawn_screen, DisplayQuality , GameState , Volume , TEXT_COLOR } ;
117
130
118
131
// This plugin will contain the game. In this case, it's just be a screen that will
119
132
// display the current settings for 5 seconds before returning to the menu
120
133
pub fn game_plugin ( app : & mut App ) {
121
- app. add_systems ( OnEnter ( GameState :: Game ) , game_setup)
134
+ app. add_systems ( OnEnter ( GameState :: Game ) , ( game_setup, play_music ) )
122
135
. add_systems ( Update , game. run_if ( in_state ( GameState :: Game ) ) )
123
- . add_systems ( OnExit ( GameState :: Game ) , despawn_screen :: < OnGameScreen > ) ;
136
+ . add_systems ( OnExit ( GameState :: Game ) , ( despawn_screen :: < OnGameScreen > , stop_music ) ) ;
124
137
}
125
138
126
139
// Tag component used to tag entities added on the game screen
@@ -229,6 +242,8 @@ mod menu {
229
242
prelude:: * ,
230
243
} ;
231
244
245
+ use crate :: { play_music, stop_music, VOLUME_MAX } ;
246
+
232
247
use super :: { despawn_screen, DisplayQuality , GameState , Volume , TEXT_COLOR } ;
233
248
234
249
// This plugin manages the menu, with 5 different screens:
@@ -265,14 +280,14 @@ mod menu {
265
280
despawn_screen :: < OnDisplaySettingsMenuScreen > ,
266
281
)
267
282
// Systems to handle the sound settings screen
268
- . add_systems ( OnEnter ( MenuState :: SettingsSound ) , sound_settings_menu_setup)
283
+ . add_systems ( OnEnter ( MenuState :: SettingsSound ) , ( sound_settings_menu_setup, play_music ) )
269
284
. add_systems (
270
285
Update ,
271
286
setting_button :: < Volume > . run_if ( in_state ( MenuState :: SettingsSound ) ) ,
272
287
)
273
288
. add_systems (
274
289
OnExit ( MenuState :: SettingsSound ) ,
275
- despawn_screen :: < OnSoundSettingsMenuScreen > ,
290
+ ( despawn_screen :: < OnSoundSettingsMenuScreen > , stop_music ) ,
276
291
)
277
292
// Common systems to all screens that handles buttons behavior
278
293
. add_systems (
@@ -663,7 +678,7 @@ mod menu {
663
678
Children :: spawn( (
664
679
Spawn ( ( Text :: new( "Volume" ) , button_text_style. clone( ) ) ) ,
665
680
SpawnWith ( move |parent: & mut ChildSpawner | {
666
- for volume_setting in [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] {
681
+ for volume_setting in 0 .. VOLUME_MAX {
667
682
let mut entity = parent. spawn( (
668
683
Button ,
669
684
Node {
@@ -735,3 +750,30 @@ fn despawn_screen<T: Component>(to_despawn: Query<Entity, With<T>>, mut commands
735
750
commands. entity ( entity) . despawn ( ) ;
736
751
}
737
752
}
753
+
754
+ fn stop_music (
755
+ playing_sounds_query : Query < AnyOf < ( & AudioSink , & SpatialAudioSink ) > >
756
+ ) {
757
+ for ( audio_sink, spatial_audio_sink) in & playing_sounds_query {
758
+ if let Some ( audio_sink) = audio_sink {
759
+ audio_sink. stop ( ) ;
760
+ }
761
+ if let Some ( spatial_audio_sink) = spatial_audio_sink {
762
+ spatial_audio_sink. stop ( ) ;
763
+ }
764
+ }
765
+ }
766
+
767
+ fn play_music (
768
+ mut commands : Commands ,
769
+ music : Res < MenuMusic > ,
770
+ ) {
771
+ commands. spawn ( ( AudioPlayer ( music. clone ( ) ) , PlaybackSettings :: DESPAWN ) ) ;
772
+ }
773
+
774
+ fn translate_discreet_volume_to_global_volume (
775
+ volume : Res < Volume > ,
776
+ mut global_volume : ResMut < GlobalVolume > ,
777
+ ) {
778
+ global_volume. volume = bevy:: audio:: Volume :: Linear ( volume. 0 as f32 / VOLUME_MAX as f32 ) ;
779
+ }
0 commit comments