fix(physics): restore fixed-point rail movement

Replace the guessed variable-rate floating integration with the original 10 ms
millipixel step, 15-unit gravity, and 3800-unit speed limit. Restore every
registered type-2 Real48 response pair, one-sided start-to-end orientation, and
the original normal/tangent velocity transform validated against live shooter
wall traces.

Restore repeat-driven plunger charging and its release-time randomized clamp.
The shooter route now follows table orientation instead of coordinate-specific
gate exceptions. Remove the synthetic ball-search impulse so future stuck balls
remain visible reconstruction failures, and include collision ids in deterministic
traces for differential work on circles and triggers.

Test Plan:
- `cargo test --all-targets` -- 42 passed
- `cargo clippy --all-targets -- -D warnings` -- passed
- `cargo build --profile production` -- passed
- charged launcher scenario cleared the shooter lane -- passed
- all recovered rails accepted front-side and rejected back-side probes
- `git diff --cached --check` -- passed
This commit is contained in:
2026-08-22 20:42:47 +02:00
parent c50ed39a35
commit 7caf460022
8 changed files with 502 additions and 260 deletions
+3 -1
View File
@@ -152,6 +152,7 @@ pub struct Snapshot {
pub claw: ClawSnapshot,
pub flippers: FlipperSnapshot,
pub launcher_charge: f32,
pub collision_id: Option<u8>,
pub events: Vec<String>,
}
@@ -255,6 +256,7 @@ impl Simulation {
right_raised: self.game.flippers.right_raised,
},
launcher_charge: self.game.launcher_charge,
collision_id: self.game.last_collision_id,
events: events
.into_iter()
.map(|event| format!("{event:?}"))
@@ -336,7 +338,7 @@ mod tests {
let mut simulation = Simulation::new(Scenario::Launcher, 1);
simulation.advance_to(60);
assert!(simulation.game.ball.in_launcher);
assert!((0.49..=0.51).contains(&simulation.game.launcher_charge));
assert!((0.09..=0.11).contains(&simulation.game.launcher_charge));
simulation.advance_to(121);
assert!(!simulation.game.ball.in_launcher);