Remove the live-fitted upward and downward flipper polynomials. Port the reconstructed 1000:7ed9 path with delta-specific pivots and record edges, integer cross-product and radius gates, penetration, response-record gain, wrapping velocity updates, and the final position delta. Use resting records on press and the already-raised records on release, correct the original delta direction, and apply each edge to both live ball slots. Keep render-facing Vec2 projections, but adjust their float representation by ULPs so every gameplay millipixel round-trips exactly instead of losing reconstructed integer results. Test Plan: - `bash original/tools/test_reconstructed_c.sh` -- passed during raised-record reference capture - `cargo test --all-targets` -- passed, 62 tests - `cargo clippy --all-targets -- -D warnings` -- passed - `rumdl check tdkpin-rs/CHANGELOG.md tdkpin-rs/RECONSTRUCTION.md` -- passed - `git diff --cached --check` -- passed
40 lines
939 B
Rust
40 lines
939 B
Rust
use macroquad::prelude::Vec2;
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub struct Segment {
|
|
pub start: Vec2,
|
|
pub end: Vec2,
|
|
pub bounce: f32,
|
|
}
|
|
|
|
impl Segment {
|
|
pub const fn new(start: Vec2, end: Vec2, bounce: f32) -> Self {
|
|
Self { start, end, bounce }
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
pub fn closest_point(point: Vec2, segment: Segment) -> Vec2 {
|
|
let line = segment.end - segment.start;
|
|
let length_squared = line.length_squared();
|
|
if length_squared <= f32::EPSILON {
|
|
return segment.start;
|
|
}
|
|
let t = ((point - segment.start).dot(line) / length_squared).clamp(0.0, 1.0);
|
|
segment.start + line * t
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn closest_point_is_clamped_to_segment() {
|
|
let segment = Segment::new(Vec2::ZERO, Vec2::new(10.0, 0.0), 0.8);
|
|
assert_eq!(
|
|
closest_point(Vec2::new(12.0, 4.0), segment),
|
|
Vec2::new(10.0, 0.0)
|
|
);
|
|
}
|
|
}
|