use bevy::prelude::*; use rand::{prelude::SliceRandom, Rng}; use std::{ collections::BTreeSet, io::{BufRead, BufReader}, process::Stdio, }; fn main() { App::build() .add_plugins(DefaultPlugins) .add_startup_system(setup) .add_system(velocity_system) .add_system(move_system) .add_system(collision_system) .add_system(select_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::rgb_linear(0.03, 0.03, 0.03); const COL_SELECTED: Color = Color::rgb_linear(5.0, 5.0, 5.0); const SHOWCASE_TIMER_SECS: f32 = 3.0; fn setup( commands: &mut Commands, asset_server: Res, mut materials: ResMut>, ) { let contribs = contributors(); let texture_handle = asset_server.load("branding/icon.png"); commands .spawn(Camera2dBundle::default()) .spawn(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 mut transform = Transform::from_translation(Vec3::new(pos.0, pos.1, 0.0)); transform.scale.x *= if flipped { -1.0 } else { 1.0 }; commands .spawn((Contributor { color: col },)) .with(Velocity { translation: velocity, rotation: -dir * 5.0, }) .with_bundle(SpriteBundle { sprite: Sprite { size: Vec2::new(1.0, 1.0) * SPRITE_SIZE, resize_mode: SpriteResizeMode::Manual, }, material: materials.add(ColorMaterial { color: COL_DESELECTED * col, texture: Some(texture_handle.clone()), }), ..Default::default() }) .with(transform); let e = commands.current_entity().unwrap(); sel.order.push((name, e)); } sel.order.shuffle(&mut rnd); commands.spawn((SelectTimer, Timer::from_seconds(SHOWCASE_TIMER_SECS, true))); commands .spawn((ContributorDisplay,)) .with_bundle(TextBundle { style: Style { align_self: AlignSelf::FlexEnd, ..Default::default() }, text: Text { value: "Contributor showcase".to_string(), font: asset_server.load("fonts/FiraSans-Bold.ttf"), style: TextStyle { 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, With>, mut tq: Query, With>, mut q: Query<(&Contributor, &Handle, &mut Transform)>, ) { let mut timer_fired = false; for mut t in tq.iter_mut() { if !t.just_finished() { continue; } t.reset(); timer_fired = true; } if !timer_fired { return; } let prev = sel.idx; if (sel.idx + 1) < sel.order.len() { sel.idx += 1; } else { sel.idx = 0; } { let (_, e) = &sel.order[prev]; if let Ok((c, handle, mut tr)) = q.get_mut(*e) { deselect(&mut *materials, handle.clone(), c, &mut *tr); } } let (name, e) = &sel.order[sel.idx]; if let Ok((c, handle, mut tr)) = q.get_mut(*e) { for mut text in dq.iter_mut() { select( &mut *materials, handle.clone(), c, &mut *tr, &mut *text, name, ); } } } /// Change the modulate color to the "selected" colour, /// bring the object to the front and display the name. fn select( materials: &mut Assets, mat_handle: Handle, cont: &Contributor, trans: &mut Transform, text: &mut Text, name: &str, ) -> Option<()> { let mat = materials.get_mut(mat_handle)?; mat.color = COL_SELECTED * cont.color; trans.translation.z = 100.0; text.value = format!("Contributor: {}", name); Some(()) } /// Change the modulate color to the "deselected" colour and push /// the object to the back. fn deselect( materials: &mut Assets, mat_handle: Handle, cont: &Contributor, trans: &mut Transform, ) -> Option<()> { let mat = materials.get_mut(mat_handle)?; mat.color = COL_DESELECTED * cont.color; trans.translation.z = 0.0; Some(()) } /// Applies gravity to all entities with velocity fn velocity_system(time: Res