bevy game jam 6 entry
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

add instructions

sakurakat.systems 9b998c4b 82d9a4bd

verified
+137 -20
+63 -3
src/menus/high_score.rs
··· 1 - use crate::menus::main::enter_loading_or_gameplay_screen; 1 + use crate::asset_tracking::ResourceHandles; 2 2 use crate::menus::Menu; 3 + use crate::screens::Screen; 3 4 use crate::theme::palette::LABEL_TEXT; 4 5 use crate::theme::widget; 5 6 use crate::zaphkiel::has_bad_word; ··· 17 18 // .run_if(resource_changed::<NameField>) 18 19 // .run_if(in_state(Menu::HighScore)), 19 20 // ); 20 - app.add_systems(Update, update_name.run_if(in_state(Menu::HighScore))); 21 + app.add_systems( 22 + Update, 23 + (update_name, tick_inactive_timer).run_if(in_state(Menu::HighScore)), 24 + ); 21 25 } 22 26 23 27 fn spawn_high_score( ··· 72 76 73 77 children_spawner.spawn(widget::button("Main Menu", open_main_menu)); 74 78 }); 79 + 80 + commands.insert_resource(Inactive(Timer::from_seconds(1.0, TimerMode::Once))); 75 81 } 76 82 77 - fn open_main_menu(_: Trigger<Pointer<Click>>, mut next_menu: ResMut<NextState<Menu>>) { 83 + fn enter_loading_or_gameplay_screen( 84 + _: Trigger<Pointer<Click>>, 85 + resource_handles: Res<ResourceHandles>, 86 + mut next_screen: ResMut<NextState<Screen>>, 87 + inactive: Option<Res<Inactive>>, 88 + ) { 89 + if inactive.is_some() { 90 + return; 91 + } 92 + 93 + if resource_handles.is_all_done() { 94 + next_screen.set(Screen::Gameplay); 95 + } else { 96 + next_screen.set(Screen::Loading); 97 + } 98 + } 99 + 100 + fn open_main_menu( 101 + _: Trigger<Pointer<Click>>, 102 + mut next_menu: ResMut<NextState<Menu>>, 103 + inactive: Option<Res<Inactive>>, 104 + ) { 105 + if inactive.is_some() { 106 + return; 107 + } 108 + 78 109 next_menu.set(Menu::Main); 79 110 } 80 111 81 112 #[derive(Component)] 82 113 struct TextThing; 114 + 83 115 #[derive(Resource, Debug, Eq, PartialEq)] 84 116 struct NameField(String); 85 117 ··· 89 121 } 90 122 } 91 123 124 + #[derive(Resource)] 125 + struct Inactive(Timer); 126 + 127 + fn tick_inactive_timer( 128 + mut timer: Option<ResMut<Inactive>>, 129 + time: Res<Time>, 130 + mut commands: Commands, 131 + ) { 132 + let Some(mut timer) = timer else { 133 + return; 134 + }; 135 + 136 + timer.0.tick(time.delta()); 137 + if timer.0.just_finished() { 138 + commands.remove_resource::<Inactive>(); 139 + } 140 + } 141 + 92 142 fn submit_score( 93 143 _: Trigger<Pointer<Click>>, 94 144 singleton: Res<ParrylordSingleton>, 95 145 mut name_field: ResMut<NameField>, 96 146 mut next_menu: ResMut<NextState<Menu>>, 97 147 mut client: BevyReqwest, 148 + inactive: Option<Res<Inactive>>, 98 149 ) { 150 + if inactive.is_some() { 151 + return; 152 + } 153 + 99 154 if has_bad_word(&name_field.0) { 100 155 name_field.0 = String::from("BAD WORD DETECTED"); 101 156 return; ··· 136 191 key: Res<ButtonInput<KeyCode>>, 137 192 mut name_field: ResMut<NameField>, 138 193 mut text_thing: Single<&mut TextSpan, With<TextThing>>, 194 + inactive: Option<Res<Inactive>>, 139 195 ) { 196 + if inactive.is_some() { 197 + return; 198 + } 199 + 140 200 let keys_pressed = key.get_just_pressed().collect::<Vec<_>>(); 141 201 142 202 if (*name_field == NameField::default()
+74 -17
src/menus/main.rs
··· 2 2 3 3 use bevy::prelude::*; 4 4 5 - use crate::audio::{pause_gameplay_music, resume_not_gameplay_music, spawn_music}; 5 + use crate::audio::{ 6 + pause_gameplay_music, pause_not_gameplay_music, resume_not_gameplay_music, spawn_music, 7 + }; 6 8 use crate::{ 7 9 asset_tracking::ResourceHandles, menus::Menu, screens::Screen, theme::widget, AudioSpawned, 8 10 }; ··· 17 19 ), 18 20 ); 19 21 20 - app.add_systems(Update, spawn_music.run_if(|res: Res<AudioSpawned>| !res.0)); 22 + app.add_systems( 23 + Update, 24 + (spawn_music, pause_gameplay_music, pause_not_gameplay_music) 25 + .chain() 26 + .run_if(|res: Res<AudioSpawned>| !res.0), 27 + ); 21 28 } 22 29 30 + const INSTRUCTIONS: &str = " 31 + WASD to move, left click to parry. 32 + 33 + On the high score screen you can type your name. 34 + 35 + The score scales exponentially with the max parries, so even though you can spam the parry, it's better to parry a lot of attacks at once. the player's damage also increases according to the number of attacks you parry. 36 + "; 37 + 23 38 fn spawn_main_menu(mut commands: Commands) { 24 39 commands.spawn(( 25 - widget::ui_root("Main Menu"), 40 + Name::new("Main Menu"), 26 41 GlobalZIndex(2), 27 42 StateScoped(Menu::Main), 28 - #[cfg(not(target_family = "wasm"))] 43 + Node { 44 + display: Display::Grid, 45 + position_type: PositionType::Absolute, 46 + width: Val::Percent(100.0), 47 + height: Val::Percent(100.0), 48 + align_items: AlignItems::Center, 49 + justify_content: JustifyContent::Center, 50 + flex_direction: FlexDirection::Column, 51 + row_gap: Val::Px(20.0), 52 + grid_template_columns: vec![RepeatedGridTrack::percent(2, 50.0)], 53 + ..default() 54 + }, 55 + Pickable::IGNORE, 29 56 children![ 30 - widget::button("Play", enter_loading_or_gameplay_screen), 31 - widget::button("Settings", open_settings_menu), 32 - widget::button("Credits", open_credits_menu), 33 - widget::button("HighScores", open_high_score_menu), 34 - widget::button("Exit", exit_app), 35 - ], 36 - #[cfg(target_family = "wasm")] 37 - children![ 38 - widget::button("Play", enter_loading_or_gameplay_screen), 39 - widget::button("Settings", open_settings_menu), 40 - widget::button("Credits", open_credits_menu), 41 - widget::button("HighScores", open_high_score_menu), 57 + ( 58 + Node { 59 + width: Val::Auto, 60 + height: Val::Auto, 61 + align_items: AlignItems::Center, 62 + justify_content: JustifyContent::Center, 63 + row_gap: Val::Px(20.0), 64 + grid_column: GridPlacement::start(1), 65 + ..default() 66 + }, 67 + Text::new(INSTRUCTIONS), 68 + ), 69 + ( 70 + Node { 71 + position_type: PositionType::Absolute, 72 + width: Val::Percent(100.0), 73 + height: Val::Percent(100.0), 74 + align_items: AlignItems::Center, 75 + justify_content: JustifyContent::Center, 76 + flex_direction: FlexDirection::Column, 77 + row_gap: Val::Px(20.0), 78 + grid_column: GridPlacement::start(2), 79 + ..default() 80 + }, 81 + // Don't block picking events for other UI roots. 82 + Pickable::IGNORE, 83 + #[cfg(not(target_family = "wasm"))] 84 + children![ 85 + widget::button("Play", enter_loading_or_gameplay_screen), 86 + widget::button("Settings", open_settings_menu), 87 + widget::button("Credits", open_credits_menu), 88 + widget::button("HighScores", open_high_score_menu), 89 + widget::button("Exit", exit_app), 90 + ], 91 + #[cfg(target_family = "wasm")] 92 + children![ 93 + widget::button("Play", enter_loading_or_gameplay_screen), 94 + widget::button("Settings", open_settings_menu), 95 + widget::button("Credits", open_credits_menu), 96 + widget::button("HighScores", open_high_score_menu), 97 + ], 98 + ) 42 99 ], 43 100 )); 44 101 } 45 102 46 - pub fn enter_loading_or_gameplay_screen( 103 + fn enter_loading_or_gameplay_screen( 47 104 _: Trigger<Pointer<Click>>, 48 105 resource_handles: Res<ResourceHandles>, 49 106 mut next_screen: ResMut<NextState<Screen>>,