Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ camera / dead zone #6

Merged
merged 4 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 96 additions & 10 deletions camera/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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(),
}
}
Expand All @@ -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<Target>>,
query_targets: Query<(&Transform, Entity), With<Target>>,
) {
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<Target>>,
query_targets: Query<(&Transform, Entity), With<Target>>,
) {
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<GizmoConfig>,
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,
);
}
}
6 changes: 5 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -38,7 +38,11 @@ fn main() {
CastlesPlugin,
HealthPlugin,
LocalPlayerPlugin,
))
// --- camera ---
.add_plugins((
CameraPlugin,
CameraDebugPlugin,
))
// --- physics ---
.add_plugins((
Expand Down