Skip to content

Commit

Permalink
Merge pull request #239 from janhohenheim/lerp
Browse files Browse the repository at this point in the history
Former-commit-id: 61151f4
  • Loading branch information
janhohenheim authored Mar 20, 2023
2 parents ff12390 + e23ddc2 commit 1f0d5bf
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 27 deletions.
14 changes: 14 additions & 0 deletions assets/config/config.game.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,17 @@ zoom_speed = 0.7
min_distance_to_objects = 4e-1
zoom_in_smoothing = 0.2
zoom_out_smoothing = 1.2

[characters]
model_sync_smoothing = 0.15
rotation_smoothing = 1.0

[player]
rotate_to_speaker_smoothness = 3.0
sprint_effect_speed_threshold = 7.0
fov_saturation_speed = 12.0
min_fov = 0.75
max_fov = 1.5

[dialog]
base_letters_per_second = 60.0
26 changes: 26 additions & 0 deletions src/file_system_interaction/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ use serde::{Deserialize, Serialize};
#[uuid = "93a7c64b-4d6e-4420-b8c1-dfca481d9387"]
pub struct GameConfig {
pub camera: Camera,
pub characters: Characters,
pub player: Player,
pub dialog: Dialog,
}

#[derive(Debug, Clone, PartialEq, Reflect, FromReflect, Serialize, Deserialize, Default)]
Expand Down Expand Up @@ -68,3 +71,26 @@ pub struct ThirdPerson {
pub zoom_in_smoothing: f32,
pub zoom_out_smoothing: f32,
}

#[derive(Debug, Clone, PartialEq, Reflect, FromReflect, Serialize, Deserialize, Default)]
#[reflect(Serialize, Deserialize)]
pub struct Characters {
pub model_sync_smoothing: f32,
pub rotation_smoothing: f32,
}

#[derive(Debug, Clone, PartialEq, Reflect, FromReflect, Serialize, Deserialize, Default)]
#[reflect(Serialize, Deserialize)]
pub struct Player {
pub rotate_to_speaker_smoothness: f32,
pub sprint_effect_speed_threshold: f32,
pub fov_saturation_speed: f32,
pub min_fov: f32,
pub max_fov: f32,
}

#[derive(Debug, Clone, PartialEq, Reflect, FromReflect, Serialize, Deserialize, Default)]
#[reflect(Serialize, Deserialize)]
pub struct Dialog {
pub base_letters_per_second: f32,
}
28 changes: 15 additions & 13 deletions src/movement/general_movement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ use std::time::Duration;

use bevy_rapier3d::prelude::*;
mod components;
use crate::file_system_interaction::config::GameConfig;
use crate::level_instantiation::spawning::AnimationEntityLink;
use crate::util::trait_extension::Vec3Ext;
use crate::util::smoothness_to_lerp_factor;
use crate::util::trait_extension::{TransformExt, Vec3Ext};
use crate::GameState;
use bevy_mod_sysfail::macros::*;
pub use components::*;
Expand Down Expand Up @@ -133,7 +135,11 @@ pub fn apply_jumping(
}
}

fn rotate_characters(time: Res<Time>, mut player_query: Query<(&Velocity, &mut Transform)>) {
fn rotate_characters(
time: Res<Time>,
mut player_query: Query<(&Velocity, &mut Transform)>,
config: Res<GameConfig>,
) {
#[cfg(feature = "tracing")]
let _span = info_span!("rotate_characters").entered();
let dt = time.delta_seconds();
Expand All @@ -146,9 +152,9 @@ fn rotate_characters(time: Res<Time>, mut player_query: Query<(&Velocity, &mut T
let target_transform =
transform.looking_at(transform.translation + horizontal_movement, up);
// Asymptotic averaging
const SMOOTHNESS: f32 = 4.;
let scale = (SMOOTHNESS * dt).min(1.);
let rotation = transform.rotation.slerp(target_transform.rotation, scale);
let smoothness = config.characters.rotation_smoothing;
let factor = smoothness_to_lerp_factor(smoothness, dt);
let rotation = transform.rotation.slerp(target_transform.rotation, factor);
transform.rotation = rotation;
}
}
Expand Down Expand Up @@ -233,18 +239,14 @@ fn sync_models(
mut commands: Commands,
without_model: Query<(&Transform, &Visibility), Without<Model>>,
mut with_model: Query<(Entity, &mut Transform, &mut Visibility, &Model)>,
game_config: Res<GameConfig>,
) -> Result<()> {
let dt = time.delta_seconds();
for (model_entity, mut model_transform, mut visibility, model) in with_model.iter_mut() {
if let Ok((target_transform, target_visibility)) = without_model.get(model.target) {
const SMOOTHNESS: f32 = 20.;
let scale = (SMOOTHNESS * dt).min(1.);
model_transform.translation = model_transform
.translation
.lerp(target_transform.translation, scale);
model_transform.rotation = model_transform
.rotation
.slerp(target_transform.rotation, scale);
let smoothness = game_config.characters.model_sync_smoothing;
let factor = smoothness_to_lerp_factor(smoothness, dt);
*model_transform = model_transform.lerp(*target_transform, factor);
*visibility = *target_visibility;
} else {
commands.entity(model_entity).despawn_recursive();
Expand Down
2 changes: 2 additions & 0 deletions src/movement/navigation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ use oxidized_navigation::{
};
use serde::{Deserialize, Serialize};

/// Manually tweaked
const CELL_WIDTH: f32 = 0.4 * npc::RADIUS;

/// Handles NPC pathfinding. Currently, all entities with the [`Follower`] component will follow the [`Player`].
pub fn navigation_plugin(app: &mut App) {
app.add_plugin(OxidizedNavigationPlugin)
// consts manually tweaked
.insert_resource(NavMeshSettings {
cell_width: CELL_WIDTH,
cell_height: 0.5 * CELL_WIDTH,
Expand Down
6 changes: 4 additions & 2 deletions src/particles.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::file_system_interaction::config::GameConfig;
use crate::level_instantiation::spawning::objects::player;
use crate::movement::general_movement::Grounded;
use crate::particles::init::init_effects;
Expand All @@ -24,16 +25,17 @@ struct SprintingParticle;
fn play_sprinting_effect(
with_player: Query<(&Transform, &Grounded, &Velocity), Without<SprintingParticle>>,
mut with_particle: Query<(&mut Transform, &mut ParticleEffect), With<SprintingParticle>>,
config: Res<GameConfig>,
) {
const SPRINT_EFFECT_SPEED_THRESHOLD: f32 = 7.;
for (player_transform, grounded, velocity) in with_player.iter() {
let horizontal_speed_squared = velocity
.linvel
.split(player_transform.up())
.horizontal
.length_squared();
for (mut particle_transform, mut effect) in with_particle.iter_mut() {
if grounded.0 && horizontal_speed_squared > SPRINT_EFFECT_SPEED_THRESHOLD.squared() {
let threshold = config.player.sprint_effect_speed_threshold;
if grounded.0 && horizontal_speed_squared > threshold.squared() {
let translation = player_transform.translation
- player_transform.up() * (player::HEIGHT / 2. + player::RADIUS);
*particle_transform = player_transform.with_translation(translation);
Expand Down
20 changes: 12 additions & 8 deletions src/player_control/player_embodiment.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use crate::file_system_interaction::audio::AudioHandles;
use crate::file_system_interaction::config::GameConfig;
use crate::movement::general_movement::{GeneralMovementSystemSet, Grounded, Jumping, Walking};
use crate::player_control::actions::{DualAxisDataExt, PlayerAction};
use crate::player_control::camera::{CameraUpdateSystemSet, IngameCamera, IngameCameraKind};
use crate::util::smoothness_to_lerp_factor;
use crate::util::trait_extension::{F32Ext, TransformExt, Vec3Ext};
use crate::world_interaction::dialog::CurrentDialog;
use crate::GameState;
Expand Down Expand Up @@ -121,20 +123,21 @@ fn handle_camera_kind(
fn handle_speed_effects(
velocities: Query<&Velocity, With<Player>>,
mut projections: Query<&mut Projection, With<IngameCamera>>,
config: Res<GameConfig>,
) {
#[cfg(feature = "tracing")]
let _span = info_span!("handle_speed_effects").entered();
for velocity in velocities.iter() {
let speed_squared = velocity.linvel.length_squared();
for mut projection in projections.iter_mut() {
if let Projection::Perspective(ref mut perspective) = projection.deref_mut() {
const MAX_SPEED_FOR_FOV: f32 = 12.;
const MIN_FOV: f32 = 0.75;
const MAX_FOV: f32 = 1.5;
let scale = (speed_squared / MAX_SPEED_FOR_FOV.squared())
let fov_saturation_speed = config.player.fov_saturation_speed;
let min_fov = config.player.min_fov;
let max_fov = config.player.max_fov;
let scale = (speed_squared / fov_saturation_speed.squared())
.min(1.0)
.squared();
perspective.fov = MIN_FOV + (MAX_FOV - MIN_FOV) * scale;
perspective.fov = min_fov + (max_fov - min_fov) * scale;
}
}
}
Expand All @@ -145,6 +148,7 @@ fn rotate_to_speaker(
mut with_player: Query<(&mut Transform, &Velocity), With<Player>>,
without_player: Query<&Transform, Without<Player>>,
current_dialog: Res<CurrentDialog>,
config: Res<GameConfig>,
) {
#[cfg(feature = "tracing")]
let _span = info_span!("rotate_to_speaker").entered();
Expand All @@ -160,9 +164,9 @@ fn rotate_to_speaker(
let target_rotation = transform
.horizontally_looking_at(speaker_transform.translation, up)
.rotation;
const SMOOTHNESS: f32 = 4.;
let scale = (SMOOTHNESS * dt).min(1.);
let rotation = transform.rotation.slerp(target_rotation, scale);
let smoothness = config.player.rotate_to_speaker_smoothness;
let factor = smoothness_to_lerp_factor(smoothness, dt);
let rotation = transform.rotation.slerp(target_rotation, factor);
transform.rotation = rotation;
}
}
Expand Down
10 changes: 6 additions & 4 deletions src/world_interaction/dialog.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::file_system_interaction::asset_loading::DialogAssets;
use crate::file_system_interaction::config::GameConfig;
use crate::player_control::actions::{ActionsFrozen, PlayerAction};
use crate::world_interaction::condition::{ActiveConditions, ConditionAddEvent, ConditionId};
use crate::world_interaction::dialog::resources::Page;
Expand Down Expand Up @@ -104,6 +105,7 @@ fn show_dialog(
actions: Query<&ActionState<PlayerAction>>,
time: Res<Time>,
mut elapsed_time: Local<f32>,
config: Res<GameConfig>,
) -> Result<()> {
let Some(mut current_dialog) = current_dialog else {
*elapsed_time = 0.0;
Expand All @@ -120,7 +122,7 @@ fn show_dialog(
ui.set_width(dialog_size.x);
ui.set_height(dialog_size.y);

let dialog_text = create_dialog_rich_text(&current_page, *elapsed_time);
let dialog_text = create_dialog_rich_text(&current_page, *elapsed_time, &config);
ui.vertical(|ui| {
ui.add_space(5.);
ui.label(&dialog_text);
Expand Down Expand Up @@ -250,9 +252,9 @@ fn set_dialog_style(style: &mut egui::Style) {
style.visuals.widgets.noninteractive.fg_stroke.color = egui::Color32::from_gray(250);
}

fn create_dialog_rich_text(page: &Page, elapsed_time: f32) -> String {
const BASE_LETTERS_PER_SECOND: f32 = 60.;
let letters_to_display = (BASE_LETTERS_PER_SECOND * page.talking_speed * elapsed_time) as usize;
fn create_dialog_rich_text(page: &Page, elapsed_time: f32, config: &GameConfig) -> String {
let base_letters_per_second = config.dialog.base_letters_per_second;
let letters_to_display = (base_letters_per_second * page.talking_speed * elapsed_time) as usize;
page.text.graphemes(true).take(letters_to_display).collect()
}

Expand Down

0 comments on commit 1f0d5bf

Please sign in to comment.