From 3261d0ba2647fa06cd9d6d0271d1e97ffca58277 Mon Sep 17 00:00:00 2001 From: Fabien JUIF Date: Thu, 23 Nov 2023 11:49:27 +0100 Subject: [PATCH] :recycle: extract camera --- Cargo.lock | 8 +++++++ Cargo.toml | 3 +++ camera/Cargo.toml | 7 ++++++ camera/src/lib.rs | 61 +++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 27 +++------------------ src/player.rs | 9 +++++-- 6 files changed, 89 insertions(+), 26 deletions(-) create mode 100644 camera/Cargo.toml create mode 100644 camera/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index f4c4ff2..f4d7a7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -383,6 +383,13 @@ dependencies = [ "rodio", ] +[[package]] +name = "bevy_camera" +version = "0.1.0" +dependencies = [ + "bevy", +] + [[package]] name = "bevy_core" version = "0.11.3" @@ -1629,6 +1636,7 @@ name = "game" version = "0.1.0" dependencies = [ "bevy", + "bevy_camera", "bevy_rapier2d", "rand", ] diff --git a/Cargo.toml b/Cargo.toml index debc578..de7b474 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,10 +5,13 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[workspace] + [dependencies] bevy = "0.11.3" bevy_rapier2d = "0.22.0" rand = "0.8.5" +bevy_camera = { path = "camera" } # Enable a small amount of optimization in debug mode [profile.dev] diff --git a/camera/Cargo.toml b/camera/Cargo.toml new file mode 100644 index 0000000..a2d10a5 --- /dev/null +++ b/camera/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "bevy_camera" +version = "0.1.0" +edition = "2021" + +[dependencies] +bevy = "0.11.3" \ No newline at end of file diff --git a/camera/src/lib.rs b/camera/src/lib.rs new file mode 100644 index 0000000..5507a7d --- /dev/null +++ b/camera/src/lib.rs @@ -0,0 +1,61 @@ +use bevy::prelude::{ + App, Bundle, Camera2dBundle, Component, Entity, Plugin, PostUpdate, Query, Transform, With, + Without, +}; + +#[derive(Component)] +pub struct Target; + +#[derive(Component)] +pub struct Camera(pub Entity); + +#[derive(Bundle)] +pub struct CameraBundle { + camera: Camera, + bundle: Camera2dBundle, +} + +impl CameraBundle { + pub fn new(target: Entity, bundle: Camera2dBundle) -> Self { + Self { + camera: Camera(target), + bundle, + } + } + + pub fn new_with_default_bundle(target: Entity) -> Self { + Self { + camera: Camera(target), + bundle: Camera2dBundle::default(), + } + } +} + +pub struct CameraPlugin; + +impl Plugin for CameraPlugin { + fn build(&self, app: &mut App) { + app.add_systems(PostUpdate, cameraman); + } +} + +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.0 != 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 { + camera_transform.translation.x = target_transform.translation.x; + camera_transform.translation.y = target_transform.translation.y; + + break; + } + } + } +} diff --git a/src/main.rs b/src/main.rs index 6ee0154..06c8925 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,18 +12,16 @@ use bevy::{ prelude::*, DefaultPlugins, }; +use bevy_camera::CameraPlugin; use bevy_rapier2d::prelude::*; use castles::CastlesPlugin; use health::HealthPlugin; use minions::MinionsPlugin; use physics::PhysicsPlugin; -use player::{LocalPlayer, LocalPlayerPlugin}; +use player::LocalPlayerPlugin; use racks::RacksPlugin; use teams::TeamsPlugin; -#[derive(Component)] -struct Camera; - fn main() { let mut app = App::new(); @@ -40,6 +38,7 @@ fn main() { CastlesPlugin, HealthPlugin, LocalPlayerPlugin, + CameraPlugin, )) // --- physics --- .add_plugins(( @@ -51,25 +50,5 @@ fn main() { gravity: Vec2::new(0.0, 0.0), ..default() }) - // --- systems --- - .add_systems(Startup, setup) - .add_systems(Update, cameraman) .run(); } - -fn setup(mut commands: Commands) { - // Camera - commands.spawn((Camera2dBundle::default(), Camera {})); -} - -fn cameraman( - mut query_camera: Query<&mut Transform, (With, Without)>, - query_player: Query<&Transform, With>, -) { - if let Ok(mut camera_transform) = query_camera.get_single_mut() { - if let Ok(player_transform) = query_player.get_single() { - camera_transform.translation.x = player_transform.translation.x; - camera_transform.translation.y = player_transform.translation.y; - } - } -} diff --git a/src/player.rs b/src/player.rs index 4cd7255..dd38985 100644 --- a/src/player.rs +++ b/src/player.rs @@ -11,6 +11,7 @@ use bevy::{ sprite::{Sprite, SpriteBundle}, time::Time, }; +use bevy_camera::{Camera, CameraBundle, Target}; use bevy_rapier2d::prelude::*; const DEFAULT_HAND_COLOR: Color = Color::rgb(0.8, 0.25, 0.24); @@ -107,7 +108,7 @@ fn setup( let team = teams.get_expect("a".into()); - commands + let entity = commands .spawn(( MaterialMesh2dBundle { mesh: meshes.add(shape::Circle::new(30.).into()).into(), @@ -139,6 +140,7 @@ fn setup( .with_health_bar_position(Vec3::new(0.0, 40.0, 0.1)) .with_health_bar_size(Vec2::new(50.0, 5.0)), Name("local_player".to_string()), + Target, team, )) .with_children(|parent| { @@ -154,7 +156,10 @@ fn setup( }, Hand {}, )); - }); + }) + .id(); + + commands.spawn(CameraBundle::new_with_default_bundle(entity)); } fn setup_ui(mut commands: Commands, asset_server: Res) {