use bevy::input::mouse::{MouseScrollUnit, MouseWheel};
use bevy::prelude::*;
use bevy::camera::visibility::RenderLayers;
use bevy_2d_screen_space_lightmaps::lightmap_plugin::lightmap_plugin::{CAMERA_LAYER_SPRITE, CAMERA_LAYER_LIGHT, LightmapPlugin, AnyNormalCamera};
const NORMAL_LIGHT_LAYER_Z: f32 = 0.0;
const OCCLUDER_LIGHT_LAYER_Z: f32 = 1.0;
const SPRITE_FLOOR_LAYER_Z: f32 = 0.0;
const SPRITE_OBJECT_LAYER_Z: f32 = 1.0;
fn main() {
let mut app = App::new();
app.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window { ..Default::default() }),
..default()
}).set(ImagePlugin::default_nearest()));
app.add_plugins(LightmapPlugin);
app.add_systems(Startup, (spawn_road_entities, spawn_truck_entities));
app.add_systems(Update, (move_truck, camera_movement));
app.run();
}
fn spawn_road_entities(
mut commands: Commands,
asset_server: Res<AssetServer>
) {
let road_tex = asset_server.load("sample_art/road_segment.png");
let grass_tex = asset_server.load("sample_art/grass.png");
let y_top = -64.0 * 5.0;
for i in 0..11 {
commands.spawn((
Sprite {
image: road_tex.clone(),
..default()
},
Transform::from_xyz(64.0, y_top + 64.0 * i as f32, SPRITE_FLOOR_LAYER_Z),
)).insert(RenderLayers::from_layers(CAMERA_LAYER_SPRITE));
commands.spawn((
Sprite {
image: grass_tex.clone(),
..default()
},
Transform::from_xyz(96.0, y_top + 64.0 * i as f32, SPRITE_FLOOR_LAYER_Z),
)).insert(RenderLayers::from_layers(CAMERA_LAYER_SPRITE));
commands.spawn((
Sprite {
image: grass_tex.clone(),
flip_x: true,
flip_y: false,
..default()
},
Transform::from_xyz(32.0, y_top + 64.0 * i as f32, SPRITE_FLOOR_LAYER_Z),
)).insert(RenderLayers::from_layers(CAMERA_LAYER_SPRITE));
}
let street_light_tex = asset_server.load("sample_art/street_light.png");
let y_top = -64.0 * 5.0 + 32.0;
for i in 0..5 {
commands.spawn((
Sprite {
image: street_light_tex.clone(),
..default()
},
Transform::from_xyz(64.0 + 31.0, y_top + 128.0 * i as f32, SPRITE_OBJECT_LAYER_Z),
)).insert(RenderLayers::from_layers(CAMERA_LAYER_SPRITE));
commands.spawn((
Sprite {
image: street_light_tex.clone(),
flip_x: true,
flip_y: false,
..default()
},
Transform::from_xyz(31.0, y_top + 128.0 * i as f32, SPRITE_OBJECT_LAYER_Z),
)).insert(RenderLayers::from_layers(CAMERA_LAYER_SPRITE));
}
let yellow_light_corona_tex = asset_server.load("sample_art/yellow_light_corona.png");
let y_top = -64.0 * 5.0 + 32.0;
for i in 0..5 {
commands.spawn((
Sprite {
image: yellow_light_corona_tex.clone(),
..default()
},
Transform::from_xyz(64.0 + 25.0, y_top + 128.0 * i as f32, NORMAL_LIGHT_LAYER_Z),
)).insert(RenderLayers::from_layers(CAMERA_LAYER_LIGHT));
commands.spawn((
Sprite {
image: yellow_light_corona_tex.clone(),
flip_x: true,
flip_y: false,
..default()
},
Transform::from_xyz(38.0, y_top + 128.0 * i as f32, NORMAL_LIGHT_LAYER_Z),
)).insert(RenderLayers::from_layers(CAMERA_LAYER_LIGHT));
}
}
#[derive(Component)]
pub struct TruckEntity;
#[derive(Resource)]
pub struct TruckDirection {
pub forward: bool
}
const TRUCK_START_Y: f32 = 64.0 * 5.0 - 77.0;
const TRUCK_BOTTOM_Y: f32 = -310.0;
fn spawn_truck_entities(
mut commands: Commands,
asset_server: Res<AssetServer>
) {
let _truck_id = commands.spawn((
Sprite {
image: asset_server.load("sample_art/truck_sprite.png"),
..default()
},
Transform::from_xyz(64.0, TRUCK_START_Y, SPRITE_OBJECT_LAYER_Z),
))
.insert(RenderLayers::from_layers(CAMERA_LAYER_SPRITE))
.insert(TruckEntity)
.id();
commands.insert_resource(TruckDirection { forward: true });
commands.spawn((
Sprite {
image: asset_server.load("sample_art/truck_light_occluder.png"),
..default()
},
Transform::from_xyz(64.0, TRUCK_START_Y, OCCLUDER_LIGHT_LAYER_Z),
))
.insert(RenderLayers::from_layers(CAMERA_LAYER_LIGHT))
.insert(TruckEntity);
commands.spawn((
Sprite {
image: asset_server.load("sample_art/double_light_cone.png"),
..default()
},
Transform::from_xyz(64.0, TRUCK_START_Y - 51.0, NORMAL_LIGHT_LAYER_Z + 0.1),
))
.insert(RenderLayers::from_layers(CAMERA_LAYER_LIGHT))
.insert(TruckEntity);
commands.spawn((
Sprite {
image: asset_server.load("sample_art/rear_lights.png"),
..default()
},
Transform::from_xyz(64.0, TRUCK_START_Y + 40.0 + 15.0, NORMAL_LIGHT_LAYER_Z),
))
.insert(RenderLayers::from_layers(CAMERA_LAYER_LIGHT))
.insert(TruckEntity);
}
fn move_truck(
mut truck_q: Query<&mut Transform, With<TruckEntity>>,
mut truck_dir: ResMut<TruckDirection>,
time: Res<Time>,
) {
let speed = 32.0 * time.delta_secs();
for mut transform in truck_q.iter_mut() {
if truck_dir.forward {
transform.translation.y -= speed;
if transform.translation.y <= TRUCK_BOTTOM_Y {
truck_dir.forward = false;
}
} else {
transform.translation.y += speed;
if transform.translation.y >= TRUCK_START_Y {
truck_dir.forward = true;
}
}
}
}
pub fn camera_movement(
mut wheel: MessageReader<MouseWheel>,
mut query: Query<&mut Projection, With<AnyNormalCamera>>,
) {
for ev in wheel.read() {
for ortho in query.iter_mut() {
match *ortho.into_inner() {
Projection::Orthographic(ref mut ortho) => {
match ev.unit {
MouseScrollUnit::Line => {
if ev.y > 0.0 {
ortho.scale -= 0.1;
} else if ev.y < 0.0 {
ortho.scale += 0.1;
}
}
_ => {}
}
ortho.scale = ortho.scale.clamp(0.5, 1.5);
},
_ => { }
}
}
}
}