entevsbaer/src/camera.rs

105 lines
2.8 KiB
Rust

use bevy::prelude::*;
use crate::player::Player;
#[derive(Component)]
pub struct PlayerCamera;
#[derive(Component)]
pub struct Light;
const OFFSET_X: f32 = -5.0;
const OFFSET_Y: f32 = 10.0;
const OFFSET_Z: f32 = 17.32;
pub fn setup(mut commands: Commands) {
let camera_transform = Transform::from_xyz(OFFSET_X, OFFSET_Y, OFFSET_Z)
.looking_at(Vec3::ZERO, Vec3::Y);
commands.spawn()
.insert_bundle(PerspectiveCameraBundle {
transform: camera_transform,
..Default::default()
})
.insert(PlayerCamera);
// light
let hilight_transform = Transform::from_xyz(0.0, 200.0, 0.0);
commands.spawn()
.insert_bundle(PointLightBundle {
transform: hilight_transform,
point_light: PointLight {
range: 2000.0,
radius: 200.0,
intensity: 2000.0,
shadows_enabled: true,
..Default::default()
},
..Default::default()
})
.insert(Light);
}
pub fn track_players(
time: Res<Time>,
mut queries: QuerySet<(
QueryState<&Transform, With<Player>>,
QueryState<&mut Transform, With<PlayerCamera>>,
QueryState<&mut Transform, With<Light>>,
)>,
) {
let mut min_x = None;
let mut max_x = None;
let mut max_y = None;
let mut min_z = None;
let mut max_z = None;
for transform in queries.q0().iter() {
let t = &transform.translation;
if min_x.map_or(true, |min_x| t.x < min_x) {
min_x = Some(t.x);
}
if max_x.map_or(true, |max_x| t.x > max_x) {
max_x = Some(t.x);
}
if max_y.map_or(true, |max_y| t.y > max_y) {
max_y = Some(t.y);
}
if min_z.map_or(true, |min_z| t.z < min_z) {
min_z = Some(t.z);
}
if max_z.map_or(true, |max_z| t.z > max_z) {
max_z = Some(t.z);
}
}
let target = max_y.and_then(|max_y| {
let dist = 8.0f32.max(
(max_x? - min_x?) / 2.0
).max(
(max_z? - min_z?) / 4.0
);
Some(Vec3::new(
(min_x? + max_x?) / 2.0 + OFFSET_X - dist / 2.0,
max_y + OFFSET_Y,
max_z? + OFFSET_Z + dist,
))
}).unwrap_or_else(|| Vec3::new(OFFSET_X, OFFSET_Y, OFFSET_Z));
for mut camera_transform in queries.q1().iter_mut() {
let t = &mut camera_transform.translation;
*t = *t + time.delta_seconds() * (target - *t) / 2.0;
}
if let Some(light_pos) = max_y.and_then(|max_y| {
Some(Vec3::new(
(min_x? + max_x?) / 2.0,
max_y + 5.0,
max_z? + 5.0
))
}) {
for ref mut light_transform in queries.q2().iter_mut() {
light_transform.translation = light_pos;
}
}
}