diff --git a/camera/src/lib.rs b/camera/src/lib.rs index 5507a7d..5118336 100644 --- a/camera/src/lib.rs +++ b/camera/src/lib.rs @@ -1,13 +1,36 @@ -use bevy::prelude::{ - App, Bundle, Camera2dBundle, Component, Entity, Plugin, PostUpdate, Query, Transform, With, - Without, +use bevy::{ + app::{PostStartup, Update}, + ecs::system::ResMut, + gizmos::{gizmos::Gizmos, GizmoConfig}, + math::Vec2, + prelude::{ + App, Bundle, Camera2dBundle, Component, Entity, Plugin, PostUpdate, Query, Transform, With, + Without, + }, + render::color::Color, }; #[derive(Component)] pub struct Target; #[derive(Component)] -pub struct Camera(pub Entity); +pub struct Camera { + target: Entity, // TODO: find a way to have multiple targets per camera, but also being able to have multi cameras (n-n) + dead_zone: Vec2, +} + +impl Camera { + pub fn new(target: Entity, dead_zone: Vec2) -> Self { + Self { target, dead_zone } + } + + pub fn new_default(target: Entity) -> Self { + Self { + target, + dead_zone: Vec2::new(100.0, 80.0), + } + } +} #[derive(Bundle)] pub struct CameraBundle { @@ -18,14 +41,14 @@ pub struct CameraBundle { impl CameraBundle { pub fn new(target: Entity, bundle: Camera2dBundle) -> Self { Self { - camera: Camera(target), + camera: Camera::new_default(target), bundle, } } pub fn new_with_default_bundle(target: Entity) -> Self { Self { - camera: Camera(target), + camera: Camera::new_default(target), bundle: Camera2dBundle::default(), } } @@ -35,27 +58,90 @@ pub struct CameraPlugin; impl Plugin for CameraPlugin { fn build(&self, app: &mut App) { - app.add_systems(PostUpdate, cameraman); + app.add_systems(PostStartup, center) + .add_systems(PostUpdate, cameraman); } } -fn cameraman( +fn center( mut query_camera: Query<(&mut Transform, &Camera), Without>, query_targets: Query<(&Transform, Entity), With>, ) { for (mut camera_transform, camera) in &mut query_camera { for (target_transform, target_entity) in &query_targets { - if camera.0 != target_entity { + if camera.target != target_entity { continue; } // TODO: for now we follow the first target but we could think of doing an average positions of all the targets - if camera.0 == target_entity { + if camera.target == target_entity { camera_transform.translation.x = target_transform.translation.x; camera_transform.translation.y = target_transform.translation.y; + break; + } + } + } +} + +fn cameraman( + mut query_camera: Query<(&mut Transform, &Camera), Without>, + query_targets: Query<(&Transform, Entity), With>, +) { + for (mut camera_transform, camera) in &mut query_camera { + for (target_transform, target_entity) in &query_targets { + if camera.target != target_entity { + continue; + } + + // TODO: for now we follow the first target but we could think of doing an average positions of all the targets + if camera.target == target_entity { + let diff = camera_transform.translation - target_transform.translation; + let diff_abs = diff.abs(); + + if diff_abs.x > camera.dead_zone.x { + camera_transform.translation.x = target_transform.translation.x + - if diff.x > 0. { + -camera.dead_zone.x + } else { + camera.dead_zone.x + }; + } + if diff_abs.y > camera.dead_zone.y { + camera_transform.translation.y = target_transform.translation.y + - if diff.y > 0. { + -camera.dead_zone.y + } else { + camera.dead_zone.y + }; + } break; } } } } + +pub struct CameraDebugPlugin; + +impl Plugin for CameraDebugPlugin { + fn build(&self, app: &mut App) { + app.add_systems(Update, debug); + } +} + +fn debug( + mut gizmos: Gizmos, + mut config: ResMut, + query_cameras: Query<(&Transform, &Camera)>, +) { + config.line_width = 1.0; + + for (camera_transform, camera) in &query_cameras { + gizmos.rect_2d( + camera_transform.translation.truncate(), + 0., + camera.dead_zone * 2.0, + Color::RED, + ); + } +} diff --git a/src/main.rs b/src/main.rs index 06c8925..5bb466e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ use bevy::{ prelude::*, DefaultPlugins, }; -use bevy_camera::CameraPlugin; +use bevy_camera::{CameraDebugPlugin, CameraPlugin}; use bevy_rapier2d::prelude::*; use castles::CastlesPlugin; use health::HealthPlugin; @@ -38,7 +38,11 @@ fn main() { CastlesPlugin, HealthPlugin, LocalPlayerPlugin, + )) + // --- camera --- + .add_plugins(( CameraPlugin, + CameraDebugPlugin, )) // --- physics --- .add_plugins((