mirror of
https://github.com/bevyengine/bevy
synced 2024-09-20 22:42:08 +00:00
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.
170 lines
5.1 KiB
Rust
170 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()),
|
|
}
|
|
}
|
|
}
|