use std::f32::consts::PI;
use bevy::color::palettes::css as Colors;
use bevy::prelude::*;
use bevy_asset_loader::prelude::*;
use bevy_smud::prelude::*;
use rand::{prelude::IteratorRandom, random};
fn main() {
App::new()
.add_plugins((DefaultPlugins, SmudPlugin, bevy_lospec::PalettePlugin))
.init_state::<GameState>()
.add_loading_state(
LoadingState::new(GameState::Loading)
.continue_to_state(GameState::Running)
.load_collection::<AssetHandles>(),
)
.add_systems(OnEnter(GameState::Running), setup)
.run();
}
#[derive(Clone, Eq, PartialEq, Debug, Hash, States, Default)]
enum GameState {
#[default]
Loading,
Running,
}
#[derive(Resource, AssetCollection)]
struct AssetHandles {
#[asset(path = "vinik24.json")]
palette: Handle<bevy_lospec::Palette>,
}
fn setup(
mut commands: Commands,
mut shaders: ResMut<Assets<Shader>>,
assets: Res<AssetHandles>,
palettes: Res<Assets<bevy_lospec::Palette>>,
) {
let box_sdf = shaders.add_sdf_expr("smud::sd_box(p, params.xy)");
let padding = 5.; let spacing = 70.;
let palette = palettes.get(&assets.palette).unwrap();
let clear_color = palette.lightest();
commands.insert_resource(ClearColor(clear_color));
let mut rng = rand::rng();
for i in 0..100 {
let size = Vec2::new(random::<f32>() * 20. + 1., random::<f32>() * 20. + 1.);
let x = ((i % 10) as f32 - 4.5) * spacing;
let y = ((i / 10) as f32 - 4.5) * spacing;
let transform = Transform {
scale: Vec3::splat(1.),
translation: Vec3::new(x, y, 0.),
rotation: Quat::from_rotation_z(random::<f32>() * PI),
};
let color = palette
.iter()
.filter(|c| *c != &clear_color)
.choose(&mut rng)
.copied()
.unwrap_or(Colors::PINK.into());
commands.spawn((
transform,
SmudShape {
color,
sdf: box_sdf.clone(),
bounds: Rectangle::from_size(size + padding * 2.),
params: Vec4::new(size.x / 2., size.y / 2., 0., 0.),
..default()
},
));
}
commands.spawn(Camera2d);
}