use bevy::prelude::*; use rand::{prelude::SliceRandom, Rng}; use std::collections::BTreeSet; fn main() { App::build() .add_plugins(bevy_webgl2::DefaultPlugins) .add_startup_system(setup.system()) .add_system(velocity_system.system()) .add_system(move_system.system()) .add_system(collision_system.system()) .add_system(select_system.system()) .run(); } type Contributors = BTreeSet; struct ContributorSelection { order: Vec<(String, Entity)>, idx: usize, } struct SelectTimer; struct ContributorDisplay; struct Contributor { color: [f32; 3], } struct Velocity { translation: Vec3, rotation: f32, } const GRAVITY: f32 = -9.821 * 100.0; const SPRITE_SIZE: f32 = 75.0; const COL_DESELECTED: Color = Color::rgba_linear(0.03, 0.03, 0.03, 0.92); const COL_SELECTED: Color = Color::WHITE; const SHOWCASE_TIMER_SECS: f32 = 3.0; fn setup( mut commands: Commands, asset_server: Res, mut materials: ResMut>, ) { let contribs = contributors(); let texture_handle = asset_server.load("branding/icon.png"); commands.spawn_bundle(OrthographicCameraBundle::new_2d()); commands.spawn_bundle(UiCameraBundle::default()); let mut sel = ContributorSelection { order: vec![], idx: 0, }; let mut rnd = rand::thread_rng(); for name in contribs { let pos = (rnd.gen_range(-400.0..400.0), rnd.gen_range(0.0..400.0)); let dir = rnd.gen_range(-1.0..1.0); let velocity = Vec3::new(dir * 500.0, 0.0, 0.0); let col = gen_color(&mut rnd); // some sprites should be flipped let flipped = rnd.gen_bool(0.5); let transform = Transform::from_xyz(pos.0, pos.1, 0.0); let e = commands .spawn_bundle((Contributor { color: col },)) .insert(Velocity { translation: velocity, rotation: -dir * 5.0, }) .insert_bundle(SpriteBundle { sprite: Sprite { size: Vec2::new(1.0, 1.0) * SPRITE_SIZE, resize_mode: SpriteResizeMode::Manual, flip_x: flipped, ..Default::default() }, material: materials.add(ColorMaterial { color: COL_DESELECTED * col, texture: Some(texture_handle.clone()), }), ..Default::default() }) .insert(transform) .id(); sel.order.push((name, e)); } sel.order.shuffle(&mut rnd); commands.spawn_bundle((SelectTimer, Timer::from_seconds(SHOWCASE_TIMER_SECS, true))); commands .spawn_bundle((ContributorDisplay,)) .insert_bundle(TextBundle { style: Style { align_self: AlignSelf::FlexEnd, ..Default::default() }, text: Text { sections: vec![ TextSection { value: "Contributor showcase".to_string(), style: TextStyle { font: asset_server.load("fonts/FiraSans-Bold.ttf"), font_size: 60.0, color: Color::WHITE, }, }, TextSection { value: "".to_string(), style: TextStyle { font: asset_server.load("fonts/FiraSans-Bold.ttf"), font_size: 60.0, color: Color::WHITE, }, }, ], ..Default::default() }, ..Default::default() }); commands.insert_resource(sel); } /// Finds the next contributor to display and selects the entity fn select_system( mut materials: ResMut>, mut sel: ResMut, mut dq: Query<&mut Text, With>, mut tq: Query<&mut Timer, With>, mut q: Query<(&Contributor, &Handle, &mut Transform)>, time: Res