93 lines
2.6 KiB
Rust
93 lines
2.6 KiB
Rust
use bevy::{
|
|
prelude::*,
|
|
render::camera::{ScalingMode, WindowOrigin},
|
|
};
|
|
use bevy_inspector_egui::{Inspectable, RegisterInspectable};
|
|
|
|
use crate::util::{move_towards_vec3, vec3_lerp};
|
|
|
|
pub struct GameCameraPlugin;
|
|
|
|
impl Plugin for GameCameraPlugin {
|
|
fn build(&self, app: &mut App) {
|
|
app.register_inspectable::<CameraFollow>()
|
|
.add_startup_system(camera_setup)
|
|
.add_system_to_stage(CoreStage::PostUpdate, camera_system);
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Inspectable, PartialEq, Reflect)]
|
|
pub enum FollowMovement {
|
|
Instant,
|
|
Linear(f32),
|
|
Smooth(f32),
|
|
}
|
|
|
|
impl Default for FollowMovement {
|
|
fn default() -> Self {
|
|
Self::Instant
|
|
}
|
|
}
|
|
|
|
#[derive(Default, Component, Reflect, Inspectable)]
|
|
#[reflect(Component)]
|
|
pub struct CameraFollow {
|
|
pub priority: i32,
|
|
pub movement: FollowMovement,
|
|
}
|
|
|
|
fn camera_setup(mut commands: Commands) {
|
|
commands.spawn((
|
|
Name::new("Camera"),
|
|
Camera2dBundle {
|
|
projection: OrthographicProjection {
|
|
scaling_mode: ScalingMode::FixedHorizontal(512.0),
|
|
window_origin: WindowOrigin::BottomLeft,
|
|
..default()
|
|
},
|
|
camera_2d: Camera2d {
|
|
clear_color: bevy::core_pipeline::clear_color::ClearColorConfig::Custom(
|
|
Color::rgb(0.0, 0.0, 0.0),
|
|
),
|
|
},
|
|
..default()
|
|
},
|
|
));
|
|
}
|
|
|
|
fn camera_system(
|
|
time: Res<Time>,
|
|
mut camera_query: Query<&mut Transform, With<Camera2d>>,
|
|
follow_query: Query<(&Transform, &CameraFollow), Without<Camera2d>>,
|
|
) {
|
|
let (target, follow) = match follow_query
|
|
.iter()
|
|
.max_by_key(|(_transform, follow)| follow.priority)
|
|
{
|
|
Some(followed) => followed,
|
|
None => return,
|
|
};
|
|
|
|
for mut camera_transform in camera_query.iter_mut() {
|
|
match follow.movement {
|
|
FollowMovement::Instant => {
|
|
camera_transform.translation = target.translation * Vec3::new(0.0, 1.0, 1.0)
|
|
}
|
|
FollowMovement::Linear(speed) => {
|
|
camera_transform.translation = move_towards_vec3(
|
|
camera_transform.translation,
|
|
target.translation * Vec3::new(0.0, 1.0, 1.0),
|
|
speed * time.delta_seconds(),
|
|
)
|
|
}
|
|
FollowMovement::Smooth(speed) => {
|
|
camera_transform.translation = vec3_lerp(
|
|
camera_transform.translation,
|
|
target.translation * Vec3::new(0.0, 1.0, 1.0),
|
|
speed * time.delta_seconds(),
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|