use bevy::prelude::*;
#[derive(Component)]
pub struct Camera2DController {
pub speed: f32,
pub allowed_distance: f32,
pub mode: Camera2DMode,
pub target_entity: Entity,
pub is_at_target: bool,
}
impl Camera2DController {
pub fn new_follow_with_speed(target_entity: Entity, speed: f32) -> Self {
Self {
speed,
allowed_distance: 100.0,
mode: Camera2DMode::Follow,
target_entity,
is_at_target: true,
}
}
}
pub enum Camera2DMode {
Follow,
Move,
}
pub fn camera_2d_controller_system(
mut camera_query: Query<(&mut Transform, &mut Camera2DController)>,
target_query: Query<&Transform, Without<Camera2DController>>,
time: Res<Time>,
) {
for (mut camera_transform, mut controller) in camera_query.iter_mut() {
let target_transform = match target_query.get(controller.target_entity) {
Ok(t) => t,
Err(_) => continue,
};
let mut movement_vector = target_transform.translation - camera_transform.translation;
match controller.mode {
Camera2DMode::Follow => {
if movement_vector.x < -controller.allowed_distance {
camera_transform.translation.x =
target_transform.translation.x + controller.allowed_distance;
}
if movement_vector.x > controller.allowed_distance {
camera_transform.translation.x =
target_transform.translation.x - controller.allowed_distance;
}
if movement_vector.y < -controller.allowed_distance {
camera_transform.translation.y =
target_transform.translation.y + controller.allowed_distance;
}
if movement_vector.y > controller.allowed_distance {
camera_transform.translation.y =
target_transform.translation.y - controller.allowed_distance;
}
controller.is_at_target = true;
}
Camera2DMode::Move => {
movement_vector.z = 0.0;
if movement_vector.length() < controller.speed / (1.0 / time.delta_seconds()) {
camera_transform.translation.x = target_transform.translation.x;
camera_transform.translation.y = target_transform.translation.y;
controller.is_at_target = true;
} else {
let normalized_movement_vector = movement_vector.normalize_or_zero();
let movement =
normalized_movement_vector * controller.speed * time.delta_seconds();
camera_transform.translation += movement;
controller.is_at_target = false;
}
}
}
}
}
pub struct Camera2DPlugin;
impl Plugin for Camera2DPlugin {
fn build(&self, app: &mut App) {
app.add_systems(PostUpdate, camera_2d_controller_system);
}
}