diff --git a/camera/src/lib.rs b/camera/src/lib.rs index 45771ff..94b2544 100644 --- a/camera/src/lib.rs +++ b/camera/src/lib.rs @@ -7,16 +7,17 @@ use bevy::{ system::{Commands, Res, ResMut}, }, gizmos::{gizmos::Gizmos, GizmoConfig}, - math::{Vec2, Vec3}, + log::{debug, warn}, + math::{self, Vec2, Vec3}, prelude::{ - default, App, Camera2dBundle, Entity, Plugin, PostUpdate, Query, Transform, With, Without, + default, App, Camera2dBundle, Entity, Plugin, PostUpdate, Query, Time, Timer, TimerMode, + Transform, With, Without, }, render::{ color::Color, mesh::{shape, Mesh}, }, sprite::{ColorMaterial, MaterialMesh2dBundle}, - time::Time, }; #[derive(Component)] @@ -31,7 +32,8 @@ pub struct Camera { // it allow us to place the camera a bit ahead of time look_at: Vec3, ahead_factor: Vec3, - moving: bool, + traveling: bool, + center_after: Timer, } impl Camera { @@ -42,7 +44,8 @@ impl Camera { target_prev_translation: Vec3::ZERO, look_at: Vec3::ZERO, ahead_factor, - moving: false, + traveling: false, + center_after: Timer::from_seconds(0.4, TimerMode::Once), } } @@ -53,7 +56,8 @@ impl Camera { target_prev_translation: Vec3::ZERO, look_at: Vec3::ZERO, ahead_factor: Vec3::ONE, - moving: false, + traveling: false, + center_after: Timer::from_seconds(0.4, TimerMode::Once), } } } @@ -119,29 +123,48 @@ fn cameraman( continue; } - // process velocity + // process target velocity let mut target_velocity = target_transform.translation - camera.target_prev_translation; - if target_velocity != Vec3::ZERO { - target_velocity /= time.delta_seconds() + let target_moving = target_velocity != Vec3::ZERO; + if target_moving { + target_velocity /= time.delta_seconds(); } camera.look_at = target_transform.translation + (target_velocity * camera.ahead_factor); camera.target_prev_translation = target_transform.translation; - // if the target is in the dead zone, do nothing on camera - let diff = camera_transform.translation - target_transform.translation; - let diff_abs = diff.abs(); - if !camera.moving - && diff_abs.x <= camera.dead_zone.x - && diff_abs.y <= camera.dead_zone.y - { - break; + // process dead zone + let diff_pos_abs = (target_transform.translation - camera_transform.translation) + .truncate() + .abs(); + let dead_zone = + diff_pos_abs.x <= camera.dead_zone.x && diff_pos_abs.y <= camera.dead_zone.y; + let centered = diff_pos_abs.x < 3.0 && diff_pos_abs.y < 3.0; + + // center after some time in the dead zone + if dead_zone && !centered && !target_moving && !camera.traveling { + camera.center_after.tick(time.delta()); + } else { + camera.center_after.reset(); + } + + // triggers travelling if we are out of dead zone + if !dead_zone { + camera.traveling = true; } - // moving camera - camera.moving = target_velocity != Vec3::ZERO; - let next_pos = (camera.look_at - camera_transform.translation) * 0.02; - camera_transform.translation.x += next_pos.x; - camera_transform.translation.y += next_pos.y; + // once the camera is moving we keep moving until we reach the center + if camera.traveling || camera.center_after.finished() { + let next_pos = camera.look_at - camera_transform.translation; + camera_transform.translation.x += next_pos.x * 0.02; + camera_transform.translation.y += next_pos.y * 0.02; + + // we arrived + if centered && !target_moving { + camera.traveling = false; + } + } + + // if the target is in the dead zone, do nothing on camera } } } diff --git a/src/main.rs b/src/main.rs index 5bb466e..63c7756 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,7 +42,7 @@ fn main() { // --- camera --- .add_plugins(( CameraPlugin, - CameraDebugPlugin, + // CameraDebugPlugin, )) // --- physics --- .add_plugins(( diff --git a/src/physics.rs b/src/physics.rs index 43c499c..d5b06b0 100644 --- a/src/physics.rs +++ b/src/physics.rs @@ -87,58 +87,58 @@ fn check_collisions( mut event_writer: EventWriter, query: Query, ) { - let mut before = collisions.clone(); - let mut events = Vec::::new(); - - // first pass detects intersections - for (e1, e2, _) in rapier_context.intersection_pairs() { - if !query.contains(e1) || !query.contains(e2) { - // entity are removed from ECS - // so we are not spawning events for them - // they will be removed in last loop - continue; - } - - let pair = EntityPair::new(e1, e2); - before.remove(&pair); - if collisions.contains(&pair) { - // we already have a started event for this intersection - continue; - } - - collisions.add(pair); - events.push(CollisionEvent::Started(pair.entity1, pair.entity2)); - } - - // second pass detects contacts - for c in rapier_context.contact_pairs() { - let e1 = c.collider1(); - let e2 = c.collider2(); - - if !query.contains(e1) || !query.contains(e2) { - // entity are removed from ECS - // so we are not spawning events for them - // they will be removed in last loop - continue; - } - - let pair = EntityPair::new(e1, e2); - before.remove(&pair); - if collisions.contains(&pair) { - // we already have a started event for this intersection - continue; - } - - collisions.add(pair); - events.push(CollisionEvent::Started(e1, e2)); - } - - // emit ended collisions - // TODO: implement iter() that return an iterator on the collisions struct - for (pair, _) in before.pairs { - collisions.remove(&pair); - events.push(CollisionEvent::Stopped(pair.entity1, pair.entity2)); - } - - event_writer.send_batch(events); + // let mut before = collisions.clone(); + // let mut events = Vec::::new(); + + // // first pass detects intersections + // for (e1, e2, _) in rapier_context.intersection_pairs() { + // if !query.contains(e1) || !query.contains(e2) { + // // entity are removed from ECS + // // so we are not spawning events for them + // // they will be removed in last loop + // continue; + // } + + // let pair = EntityPair::new(e1, e2); + // before.remove(&pair); + // if collisions.contains(&pair) { + // // we already have a started event for this intersection + // continue; + // } + + // collisions.add(pair); + // events.push(CollisionEvent::Started(pair.entity1, pair.entity2)); + // } + + // // second pass detects contacts + // for c in rapier_context.contact_pairs() { + // let e1 = c.collider1(); + // let e2 = c.collider2(); + + // if !query.contains(e1) || !query.contains(e2) { + // // entity are removed from ECS + // // so we are not spawning events for them + // // they will be removed in last loop + // continue; + // } + + // let pair = EntityPair::new(e1, e2); + // before.remove(&pair); + // if collisions.contains(&pair) { + // // we already have a started event for this intersection + // continue; + // } + + // collisions.add(pair); + // events.push(CollisionEvent::Started(e1, e2)); + // } + + // // emit ended collisions + // // TODO: implement iter() that return an iterator on the collisions struct + // for (pair, _) in before.pairs { + // collisions.remove(&pair); + // events.push(CollisionEvent::Stopped(pair.entity1, pair.entity2)); + // } + + // event_writer.send_batch(events); }