fix(physics): gate dynamic impulse on capture age
Match records 174/175 by transferring normal impulse only when the other slot capture age is nonpositive. A held slot now keeps its velocity and the moving ball resolves with the full normal velocity; successful transfer retains the original normal_velocity-1000 response. Test Plan: - cargo test --all-targets - cargo clippy --all-targets --all-features -- -D warnings - rumdl check CHANGELOG.md RECONSTRUCTION.md README.md - git diff --check
This commit is contained in:
@@ -549,6 +549,7 @@ pub fn ball_collision_response(
|
||||
spin: Real48,
|
||||
other_position: MilliVec,
|
||||
other_velocity: MilliVec,
|
||||
transfer_enabled: bool,
|
||||
) -> Option<BallCollisionResponse> {
|
||||
let mut surface_distance =
|
||||
milli_distance(subtract(other_position, old_position)).wrapping_sub(17_000);
|
||||
@@ -574,24 +575,32 @@ pub fn ball_collision_response(
|
||||
return None;
|
||||
}
|
||||
surface_distance = surface_distance.wrapping_add(3_000);
|
||||
let transfer_x = Real48::from_i32(collision_velocity)
|
||||
.multiply(normal_y)
|
||||
.divide(Real48::from_i32(length))
|
||||
.round_i32();
|
||||
let transfer_y = Real48::from_i32(collision_velocity)
|
||||
.multiply(normal_x)
|
||||
.divide(Real48::from_i32(length))
|
||||
.round_i32();
|
||||
let other_velocity = MilliVec {
|
||||
x: other_velocity.x.wrapping_add(transfer_x),
|
||||
y: other_velocity.y.wrapping_sub(transfer_y),
|
||||
let other_velocity = if transfer_enabled {
|
||||
let transfer_x = Real48::from_i32(collision_velocity)
|
||||
.multiply(normal_y)
|
||||
.divide(Real48::from_i32(length))
|
||||
.round_i32();
|
||||
let transfer_y = Real48::from_i32(collision_velocity)
|
||||
.multiply(normal_x)
|
||||
.divide(Real48::from_i32(length))
|
||||
.round_i32();
|
||||
MilliVec {
|
||||
x: other_velocity.x.wrapping_add(transfer_x),
|
||||
y: other_velocity.y.wrapping_sub(transfer_y),
|
||||
}
|
||||
} else {
|
||||
other_velocity
|
||||
};
|
||||
let (moving_velocity, moving_spin, _) = apply_response(
|
||||
velocity,
|
||||
spin,
|
||||
normal_x,
|
||||
normal_y,
|
||||
collision_velocity.wrapping_sub(1_000),
|
||||
if transfer_enabled {
|
||||
collision_velocity.wrapping_sub(1_000)
|
||||
} else {
|
||||
collision_velocity
|
||||
},
|
||||
CollisionMaterial::circle(0.9, 0.0, 0.0).real48(),
|
||||
);
|
||||
Some(BallCollisionResponse {
|
||||
@@ -930,11 +939,30 @@ mod tests {
|
||||
y: 100_000,
|
||||
},
|
||||
MilliVec::default(),
|
||||
true,
|
||||
)
|
||||
.expect("moving ball enters the 17-pixel dynamic record");
|
||||
assert_eq!(response.surface_distance, 4_000);
|
||||
assert_eq!(response.other_velocity, MilliVec { x: 3_000, y: 0 });
|
||||
assert_eq!(response.moving_velocity, MilliVec { x: -4_600, y: 0 });
|
||||
assert_eq!(response.moving_spin, Real48::ZERO);
|
||||
|
||||
let held_other = ball_collision_response(
|
||||
MilliVec {
|
||||
x: 100_000,
|
||||
y: 100_000,
|
||||
},
|
||||
MilliVec { x: 3_000, y: 0 },
|
||||
Real48::ZERO,
|
||||
MilliVec {
|
||||
x: 118_000,
|
||||
y: 100_000,
|
||||
},
|
||||
MilliVec::default(),
|
||||
false,
|
||||
)
|
||||
.expect("the held slot still presents a dynamic collision record");
|
||||
assert_eq!(held_other.other_velocity, MilliVec::default());
|
||||
assert_eq!(held_other.moving_velocity, MilliVec { x: -2_700, y: 0 });
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user