bevy_tnua::util

Struct SegmentedJumpInitialVelocityCalculator

Source
pub struct SegmentedJumpInitialVelocityCalculator { /* private fields */ }
Expand description

Calculate the kinetic energy required to jump to a certain height when different gravity is applied in different segments of the jump.

MOTIVATION: Ballistically accurate jumps where the gravity is constant don’t feel good in games. To improve the player experience, Tnua applies higher gravity in different segments of the jump (e.g. to get faster takeoff or to reduce the airtime at the tip of the jump). Being able to control the height of the jump is still vital though, and needs to be done by setting the initial upward velocity of the jump. SegmentedJumpInitialVelocityCalculator is a tool for calculating the latter from the former.

let takeoff_upward_velocity = SegmentedJumpInitialVelocityCalculator::new(jump_height)
    // When upward velocity is below 1.0, use an extra gravity of 20.0
    .add_segment(GRAVITY + 20.0, 1.0)
    // When upward velocity is between 1.0 and 2.0, use regular gravity
    .add_segment(GRAVITY, 2.0)
    // When upward velocity is higher than 2.0, use an extra gravity of 30.0
    .add_final_segment(GRAVITY + 30.0)
    // After adding all the segments, get the velocity required to make such a jump
    .required_initial_velocity()
    .expect("`add_final_segment` should have covered remaining height");

Note that:

  • Only the part of the jump where the character goes up is relevant here. The part after the peak where the character goes down may have its own varying gravity, but since that gravity can not affect the height of the jump SegmentedJumpInitialVelocityCalculator does not need to care about it.
  • Segments are calculated from top to bottom. The very top - the peak of the jump - has, by definition, zero upward velocity, so the velocity_threshold passed to it is the one at the bottom. The last segment should have INFINITY as its velocity.
  • The internal representation and calculation is with kinetic energy for a rigid body with a mass of 1.0 rather than with velocities.

Implementations§

Source§

impl SegmentedJumpInitialVelocityCalculator

Source

pub fn new(total_height: Float) -> Self

Create a SegmentedJumpInitialVelocityCalculator ready to calculate the velocity required for a jump of the specified height.

Source

pub fn add_segment( &mut self, gravity: Float, velocity_threshold: Float, ) -> &mut Self

Convert height to kinetic energy for segment under the given gravity.

The segment is specified by velocity. The bottom determined by the velocity_threshold argument and the top is the bottom of the previous call to add_segment - or the peak of the jump, if this is the first call.

If there is no height left to convert, nothing will be changed.

Source

pub fn add_final_segment(&mut self, gravity: Float) -> &mut Self

Convert the remaining height to kinetic energy under the given gravity.

Source

pub fn kinetic_energy(&self) -> Result<Float, LeftoverHeight>

The kinetic energy required to make the jump.

This should only be called after all the height was converted - otherwise it’ll return a LeftoverHeight error.

Source

pub fn kinetic_energy_to_velocity(kinetic_energy: Float) -> Float

Convert kinetic energy to velocity for a rigid body with a mass of 1.0.

Source

pub fn required_initial_velocity(&self) -> Result<Float, LeftoverHeight>

The initial upward velocity required to make the jump.

This should only be called after all the height was converted - otherwise it’ll return a LeftoverHeight error.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T, U> AsBindGroupShaderType<U> for T
where U: ShaderType, &'a T: for<'a> Into<U>,

Source§

fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U

Return the T ShaderType for self. When used in AsBindGroup derives, it is safe to assume that all images in self exist.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ConditionalSend for T
where T: Send,

Source§

impl<T> Settings for T
where T: 'static + Send + Sync,

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,