dialog WIP paths consolidation and rendering
This commit is contained in:
74
src/systems/dialog_camera.rs
Normal file
74
src/systems/dialog_camera.rs
Normal file
@@ -0,0 +1,74 @@
|
||||
use glam::Vec3;
|
||||
|
||||
use crate::world::World;
|
||||
|
||||
const CAMERA_LAG: f32 = 4.0;
|
||||
const VERTICAL_BIAS: f32 = 0.4;
|
||||
const MIN_DISTANCE: f32 = 8.0;
|
||||
const MAX_DISTANCE: f32 = 24.0;
|
||||
|
||||
pub fn dialog_camera_system(world: &mut World, delta: f32)
|
||||
{
|
||||
let Some((camera_entity, _)) = world.active_camera()
|
||||
else
|
||||
{
|
||||
return;
|
||||
};
|
||||
|
||||
let player_pos = world.player_position();
|
||||
|
||||
let character_positions: Vec<Vec3> = world
|
||||
.bubble_tags
|
||||
.all()
|
||||
.iter()
|
||||
.filter_map(|&bubble| {
|
||||
let char_entity = world.dialog_bubbles.with(bubble, |b| b.character_entity)?;
|
||||
world.transforms.with(char_entity, |t| t.position)
|
||||
})
|
||||
.collect();
|
||||
|
||||
if character_positions.is_empty()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let all_positions: Vec<Vec3> = std::iter::once(player_pos)
|
||||
.chain(character_positions.iter().copied())
|
||||
.collect();
|
||||
|
||||
let centroid =
|
||||
all_positions.iter().copied().fold(Vec3::ZERO, |a, b| a + b) / all_positions.len() as f32;
|
||||
|
||||
let max_spread = all_positions
|
||||
.iter()
|
||||
.map(|p| (*p - centroid).length())
|
||||
.fold(0.0f32, f32::max);
|
||||
|
||||
let camera_distance = (max_spread * 1.8 + MIN_DISTANCE).min(MAX_DISTANCE);
|
||||
|
||||
let to_player = (player_pos - centroid).normalize_or(Vec3::Z);
|
||||
let camera_back_dir = Vec3::new(to_player.x, 0.0, to_player.z).normalize_or(Vec3::Z);
|
||||
|
||||
let target_camera_pos =
|
||||
centroid + camera_back_dir * camera_distance + Vec3::Y * camera_distance * VERTICAL_BIAS;
|
||||
|
||||
let current_camera_pos = world
|
||||
.transforms
|
||||
.with(camera_entity, |t| t.position)
|
||||
.unwrap_or(target_camera_pos);
|
||||
|
||||
let smoothed = current_camera_pos.lerp(target_camera_pos, (CAMERA_LAG * delta).min(1.0));
|
||||
|
||||
world.transforms.with_mut(camera_entity, |t| {
|
||||
t.position = smoothed;
|
||||
});
|
||||
|
||||
let look_target = centroid + Vec3::Y * 1.0;
|
||||
|
||||
if let Some(camera) = world.cameras.get_mut(camera_entity)
|
||||
{
|
||||
let look_dir = (look_target - smoothed).normalize_or(-Vec3::Z);
|
||||
camera.yaw = look_dir.z.atan2(look_dir.x);
|
||||
camera.pitch = look_dir.y.asin();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user