CI / build-and-test (push) Successful in 1m9s
Reviewed-on: #43 Co-authored-by: Álex Román Núñez <eirexe@eirteam.moe>
70 lines
2.0 KiB
Rust
70 lines
2.0 KiB
Rust
use fixed::traits::ToFixed;
|
|
use fixed_math::SinCos;
|
|
|
|
use crate::math::{
|
|
int::{FGWide, FGi32},
|
|
vec::FGVec2,
|
|
};
|
|
|
|
/// Applies DI to a given attack direction
|
|
pub fn apply_directional_influence(
|
|
receiver_stick: FGVec2,
|
|
attack_angle: FGi32,
|
|
di_max_angle: FGi32,
|
|
) -> FGVec2 {
|
|
let (sin, cos) = attack_angle.sin_cos();
|
|
let base_launch_direction = FGVec2::new(cos, sin);
|
|
|
|
let Some(base_launch_direction) = base_launch_direction.normalize() else {
|
|
return FGVec2::ZERO;
|
|
};
|
|
|
|
if receiver_stick.length_squared().is_zero() {
|
|
return base_launch_direction;
|
|
}
|
|
|
|
let normal = FGVec2::new(-base_launch_direction.y, base_launch_direction.x);
|
|
let di_amount = receiver_stick.dot(normal);
|
|
let angle_change = di_amount * di_max_angle.to_fixed::<FGWide>();
|
|
let angle_change = angle_change.clamp(
|
|
-di_max_angle.to_fixed::<FGWide>(),
|
|
di_max_angle.to_fixed::<FGWide>(),
|
|
);
|
|
let (sin, cos) = (attack_angle + angle_change.to_fixed::<FGi32>()).sin_cos();
|
|
FGVec2::new(cos, sin).normalize_or_zero()
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use crate::{
|
|
fighter::attack::directional_influence::apply_directional_influence,
|
|
math::{int::FGi32, vec::FGVec2},
|
|
};
|
|
|
|
#[test]
|
|
fn di_zero_passes_unmodified() {
|
|
let di = apply_directional_influence(FGVec2::ZERO, FGi32::lit("0.0"), FGi32::lit("18.0"));
|
|
const EPSILON: FGi32 = FGi32::from_bits(4);
|
|
assert!(di.x.abs_diff(FGi32::ONE) < EPSILON);
|
|
assert!(di.y.abs_diff(FGi32::ZERO) < EPSILON);
|
|
}
|
|
|
|
#[test]
|
|
fn di_applies_on_the_correct_side() {
|
|
let di = apply_directional_influence(
|
|
FGVec2::lit("0.0", "1.0"),
|
|
FGi32::lit("0.0"),
|
|
FGi32::lit("18.0"),
|
|
);
|
|
assert!(di.x > FGi32::ZERO);
|
|
assert!(di.y > FGi32::ZERO);
|
|
let di = apply_directional_influence(
|
|
FGVec2::lit("0.0", "-1.0"),
|
|
FGi32::lit("0.0"),
|
|
FGi32::lit("18.0"),
|
|
);
|
|
assert!(di.x > FGi32::ZERO);
|
|
assert!(di.y < FGi32::ZERO);
|
|
}
|
|
}
|