use bevy::{
color::palettes::tailwind::{BLUE_300, BLUE_600, GRAY_200, GRAY_700, YELLOW_600},
prelude::*,
window::PrimaryWindow,
};
use bevy_lit::prelude::*;
fn main() {
App::new()
.add_plugins((DefaultPlugins, Lighting2dPlugin))
.insert_resource(ClearColor(Color::from(GRAY_200)))
.add_systems(Startup, setup)
.add_systems(Update, update_cursor_light)
.add_systems(FixedUpdate, update_moving_lights)
.run();
}
#[derive(Component)]
struct CursorLight;
#[derive(Component)]
struct MovingLights;
const X_EXTENT: f32 = 700.;
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ColorMaterial>>,
) {
commands.spawn((
Camera2d,
Lighting2dSettings {
blur: 4,
edge_intensity: 8.0,
raymarch: RaymarchSettings {
max_steps: 32,
jitter_contrib: 0.5,
sharpness: 10.,
},
..default()
},
AmbientLight2d {
intensity: 0.1,
color: Color::from(BLUE_300),
},
));
let shapes = [
meshes.add(Circle::new(50.0)),
meshes.add(Annulus::new(25.0, 50.0)),
meshes.add(Capsule2d::new(25.0, 50.0)),
meshes.add(Rhombus::new(75.0, 100.0)),
meshes.add(Rectangle::new(50.0, 100.0)),
meshes.add(RegularPolygon::new(50.0, 6)),
meshes.add(Triangle2d::new(
Vec2::Y * 50.0,
Vec2::new(-50.0, -50.0),
Vec2::new(50.0, -50.0),
)),
];
let color = materials.add(Color::from(GRAY_700));
let num_shapes = shapes.len();
for (i, shape) in shapes.into_iter().enumerate() {
commands.spawn((
Mesh2d(shape),
MeshMaterial2d(color.clone()),
LightOccluder2d::default(),
Transform::from_xyz(
-X_EXTENT / 2. + i as f32 / (num_shapes - 1) as f32 * X_EXTENT,
0.0,
0.0,
),
));
}
let moving_point_light = PointLight2d {
color: Color::from(BLUE_600),
intensity: 2.0,
outer_radius: 1100.0,
falloff: 3.0,
..default()
};
commands.spawn((
MovingLights,
Transform::default(),
Visibility::default(),
children![
(
moving_point_light.clone(),
Transform::from_xyz(-X_EXTENT + 50. / 2., 0.0, 0.0),
),
(
moving_point_light,
Transform::from_xyz(X_EXTENT + 50. / 2., 0.0, 0.0),
)
],
));
commands.spawn((
CursorLight,
PointLight2d {
color: Color::from(YELLOW_600),
intensity: 2.0,
outer_radius: 400.0,
falloff: 10.0,
..default()
},
));
}
fn update_cursor_light(
window: Single<&Window, With<PrimaryWindow>>,
camera: Single<(&Camera, &GlobalTransform), With<Lighting2dSettings>>,
mut point_light_transform: Single<&mut Transform, With<CursorLight>>,
) {
let (camera, camera_transform) = camera.into_inner();
if let Some(world_position) = window
.cursor_position()
.and_then(|cursor| camera.viewport_to_world(camera_transform, cursor).ok())
.map(|ray| ray.origin.truncate().extend(0.0))
{
point_light_transform.translation = world_position;
}
}
fn update_moving_lights(
time: Res<Time>,
mut point_light_query: Query<&mut Transform, With<MovingLights>>,
) {
for mut transform in &mut point_light_query {
transform.rotation *= Quat::from_rotation_z(time.delta_secs() / 12.0);
}
}