 284889c64b
			
		
	
	
		284889c64b
		
	
	
	
	
		
			
			An alternative to StateStages that uses SystemSets. Also includes pop and push operations since this was originally developed for my personal project which needed them.
		
			
				
	
	
		
			171 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| use bevy::prelude::*;
 | |
| 
 | |
| /// This example illustrates how to use States to control transitioning from a Menu state to an
 | |
| /// InGame state.
 | |
| fn main() {
 | |
|     App::build()
 | |
|         .add_plugins(DefaultPlugins)
 | |
|         .init_resource::<ButtonMaterials>()
 | |
|         .add_state(AppState::Menu)
 | |
|         .add_system_set(SystemSet::on_enter(AppState::Menu).with_system(setup_menu.system()))
 | |
|         .add_system_set(SystemSet::on_update(AppState::Menu).with_system(menu.system()))
 | |
|         .add_system_set(SystemSet::on_exit(AppState::Menu).with_system(cleanup_menu.system()))
 | |
|         .add_system_set(SystemSet::on_enter(AppState::InGame).with_system(setup_game.system()))
 | |
|         .add_system_set(
 | |
|             SystemSet::on_update(AppState::InGame)
 | |
|                 .with_system(movement.system())
 | |
|                 .with_system(change_color.system()),
 | |
|         )
 | |
|         .run();
 | |
| }
 | |
| 
 | |
| #[derive(Clone, Eq, PartialEq)]
 | |
| enum AppState {
 | |
|     Menu,
 | |
|     InGame,
 | |
| }
 | |
| 
 | |
| struct MenuData {
 | |
|     button_entity: Entity,
 | |
| }
 | |
| 
 | |
| fn setup_menu(
 | |
|     mut commands: Commands,
 | |
|     asset_server: Res<AssetServer>,
 | |
|     button_materials: Res<ButtonMaterials>,
 | |
| ) {
 | |
|     commands
 | |
|         // ui camera
 | |
|         .spawn(UiCameraBundle::default())
 | |
|         .spawn(ButtonBundle {
 | |
|             style: Style {
 | |
|                 size: Size::new(Val::Px(150.0), Val::Px(65.0)),
 | |
|                 // center button
 | |
|                 margin: Rect::all(Val::Auto),
 | |
|                 // horizontally center child text
 | |
|                 justify_content: JustifyContent::Center,
 | |
|                 // vertically center child text
 | |
|                 align_items: AlignItems::Center,
 | |
|                 ..Default::default()
 | |
|             },
 | |
|             material: button_materials.normal.clone(),
 | |
|             ..Default::default()
 | |
|         })
 | |
|         .with_children(|parent| {
 | |
|             parent.spawn(TextBundle {
 | |
|                 text: Text::with_section(
 | |
|                     "Play",
 | |
|                     TextStyle {
 | |
|                         font: asset_server.load("fonts/FiraSans-Bold.ttf"),
 | |
|                         font_size: 40.0,
 | |
|                         color: Color::rgb(0.9, 0.9, 0.9),
 | |
|                     },
 | |
|                     Default::default(),
 | |
|                 ),
 | |
|                 ..Default::default()
 | |
|             });
 | |
|         });
 | |
|     commands.insert_resource(MenuData {
 | |
|         button_entity: commands.current_entity().unwrap(),
 | |
|     });
 | |
| }
 | |
| 
 | |
| fn menu(
 | |
|     mut state: ResMut<State<AppState>>,
 | |
|     button_materials: Res<ButtonMaterials>,
 | |
|     mut interaction_query: Query<
 | |
|         (&Interaction, &mut Handle<ColorMaterial>),
 | |
|         (Mutated<Interaction>, With<Button>),
 | |
|     >,
 | |
| ) {
 | |
|     for (interaction, mut material) in interaction_query.iter_mut() {
 | |
|         match *interaction {
 | |
|             Interaction::Clicked => {
 | |
|                 *material = button_materials.pressed.clone();
 | |
|                 state.set_next(AppState::InGame).unwrap();
 | |
|             }
 | |
|             Interaction::Hovered => {
 | |
|                 *material = button_materials.hovered.clone();
 | |
|             }
 | |
|             Interaction::None => {
 | |
|                 *material = button_materials.normal.clone();
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| fn cleanup_menu(mut commands: Commands, menu_data: Res<MenuData>) {
 | |
|     commands.despawn_recursive(menu_data.button_entity);
 | |
| }
 | |
| 
 | |
| fn setup_game(
 | |
|     mut commands: Commands,
 | |
|     asset_server: Res<AssetServer>,
 | |
|     mut materials: ResMut<Assets<ColorMaterial>>,
 | |
| ) {
 | |
|     let texture_handle = asset_server.load("branding/icon.png");
 | |
|     commands
 | |
|         .spawn(OrthographicCameraBundle::new_2d())
 | |
|         .spawn(SpriteBundle {
 | |
|             material: materials.add(texture_handle.into()),
 | |
|             ..Default::default()
 | |
|         });
 | |
| }
 | |
| 
 | |
| const SPEED: f32 = 100.0;
 | |
| fn movement(
 | |
|     time: Res<Time>,
 | |
|     input: Res<Input<KeyCode>>,
 | |
|     mut query: Query<&mut Transform, With<Sprite>>,
 | |
| ) {
 | |
|     for mut transform in query.iter_mut() {
 | |
|         let mut direction = Vec3::ZERO;
 | |
|         if input.pressed(KeyCode::Left) {
 | |
|             direction.x += 1.0;
 | |
|         }
 | |
|         if input.pressed(KeyCode::Right) {
 | |
|             direction.x -= 1.0;
 | |
|         }
 | |
|         if input.pressed(KeyCode::Up) {
 | |
|             direction.y += 1.0;
 | |
|         }
 | |
|         if input.pressed(KeyCode::Down) {
 | |
|             direction.y -= 1.0;
 | |
|         }
 | |
| 
 | |
|         if direction != Vec3::ZERO {
 | |
|             transform.translation += direction.normalize() * SPEED * time.delta_seconds();
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| fn change_color(
 | |
|     time: Res<Time>,
 | |
|     mut assets: ResMut<Assets<ColorMaterial>>,
 | |
|     query: Query<&Handle<ColorMaterial>, With<Sprite>>,
 | |
| ) {
 | |
|     for handle in query.iter() {
 | |
|         let material = assets.get_mut(handle).unwrap();
 | |
|         material
 | |
|             .color
 | |
|             .set_b((time.seconds_since_startup() * 5.0).sin() as f32 + 2.0);
 | |
|     }
 | |
| }
 | |
| 
 | |
| struct ButtonMaterials {
 | |
|     normal: Handle<ColorMaterial>,
 | |
|     hovered: Handle<ColorMaterial>,
 | |
|     pressed: Handle<ColorMaterial>,
 | |
| }
 | |
| 
 | |
| impl FromWorld for ButtonMaterials {
 | |
|     fn from_world(world: &mut World) -> Self {
 | |
|         let mut materials = world.get_resource_mut::<Assets<ColorMaterial>>().unwrap();
 | |
|         ButtonMaterials {
 | |
|             normal: materials.add(Color::rgb(0.15, 0.15, 0.15).into()),
 | |
|             hovered: materials.add(Color::rgb(0.25, 0.25, 0.25).into()),
 | |
|             pressed: materials.add(Color::rgb(0.35, 0.75, 0.35).into()),
 | |
|         }
 | |
|     }
 | |
| }
 |