fix(game): restore one-shot magnetic fields
Replace the global timed magnet and drain teleport with the three recovered field records. Map top targets 150-152 to center field 6 and outlane fields 153-154, apply upward pull only inside each registered rectangle, and deactivate the field after it pulls the ball through its upper boundary. Render each active field from its exact original active-table rectangle instead of drawing invented yellow triangles. Test Plan: - `cargo test --all-targets` -- 48 passed - `cargo clippy --all-targets -- -D warnings` -- passed - production build plus Windows GNU and macOS checks -- passed - live field-153 entry direction matched and Rust field lifecycle test passed - `git diff --cached --check` -- passed
This commit is contained in:
+16
-13
@@ -410,19 +410,22 @@ impl App {
|
||||
let index = usize::from(game.player().diamond_segments.min(9) - 1);
|
||||
draw_texture(&self.assets.diamond[index], 123.0, 298.0, WHITE);
|
||||
}
|
||||
if game.magnets > 0.0 {
|
||||
for x in [18.0, 296.0] {
|
||||
draw_triangle(
|
||||
vec2(x, 345.0),
|
||||
vec2(x - 7.0, 359.0),
|
||||
vec2(x + 7.0, 359.0),
|
||||
YELLOW,
|
||||
);
|
||||
draw_triangle(
|
||||
vec2(x, 367.0),
|
||||
vec2(x - 7.0, 381.0),
|
||||
vec2(x + 7.0, 381.0),
|
||||
YELLOW,
|
||||
for (object_id, region) in [
|
||||
(6, Rect::new(151.0, 389.0, 13.0, 49.0)),
|
||||
(153, Rect::new(11.0, 344.0, 13.0, 49.0)),
|
||||
(154, Rect::new(291.0, 346.0, 13.0, 49.0)),
|
||||
] {
|
||||
if game.magnetic_field_active(object_id) {
|
||||
draw_texture_ex(
|
||||
&self.assets.active_table,
|
||||
region.x,
|
||||
region.y,
|
||||
WHITE,
|
||||
DrawTextureParams {
|
||||
dest_size: Some(vec2(region.w, region.h)),
|
||||
source: Some(region),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+58
-15
@@ -199,7 +199,6 @@ pub struct Game {
|
||||
pub bonus: u32,
|
||||
pub wheel_holes: [bool; 5],
|
||||
pub top_targets: [bool; 3],
|
||||
pub magnets: f32,
|
||||
pub tilted: bool,
|
||||
pub flippers: Flippers,
|
||||
pub claw: Claw,
|
||||
@@ -237,7 +236,6 @@ impl Game {
|
||||
bonus: 0,
|
||||
wheel_holes: [false; 5],
|
||||
top_targets: [false; 3],
|
||||
magnets: 0.0,
|
||||
tilted: false,
|
||||
flippers: Flippers::default(),
|
||||
claw: Claw::default(),
|
||||
@@ -381,7 +379,6 @@ impl Game {
|
||||
fn fixed_update(&mut self, dt: f32, events: &mut Vec<Event>) {
|
||||
self.bumper_cooldown = (self.bumper_cooldown - dt).max(0.0);
|
||||
self.nudge_cooldown = (self.nudge_cooldown - dt).max(0.0);
|
||||
self.magnets = (self.magnets - dt).max(0.0);
|
||||
self.wheel_animation = (self.wheel_animation - dt).max(0.0);
|
||||
self.nudge_shake = (self.nudge_shake - dt).max(0.0);
|
||||
for flash in &mut self.bumper_flash {
|
||||
@@ -407,6 +404,7 @@ impl Game {
|
||||
let mut velocity = MilliVec::from_velocity_per_second(self.ball.velocity);
|
||||
velocity.y += GRAVITY_MILLI_PER_STEP;
|
||||
velocity.clamp_speed(MAXIMUM_SPEED_MILLI_PER_STEP);
|
||||
self.apply_magnetic_fields(old_position, &mut velocity);
|
||||
let movement_velocity = velocity;
|
||||
let mut position = old_position.add(velocity);
|
||||
let mut best_collision: Option<(u8, bool, CollisionResponse)> = None;
|
||||
@@ -468,15 +466,7 @@ impl Game {
|
||||
|
||||
if let Some(wall_id) = hit_wall {
|
||||
if wall_id == 2 {
|
||||
if self.magnets > 0.0
|
||||
&& (self.ball.position.x < 145.0 || self.ball.position.x > 175.0)
|
||||
{
|
||||
self.ball.position.y = 410.0;
|
||||
self.ball.velocity = vec2((157.0 - self.ball.position.x) * 2.0, -245.0);
|
||||
self.magnets = 0.0;
|
||||
} else {
|
||||
self.drain(events);
|
||||
}
|
||||
self.drain(events);
|
||||
return;
|
||||
}
|
||||
if wall_id == 25
|
||||
@@ -691,7 +681,8 @@ impl Game {
|
||||
events.push(Event::Target);
|
||||
if (150..=152).contains(&sensor.id) {
|
||||
self.top_targets[usize::from(sensor.id - 150)] = true;
|
||||
self.magnets = self.magnets.max(0.3);
|
||||
let field_id = [153, 6, 154][usize::from(sensor.id - 150)];
|
||||
self.object_active[field_id] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -705,6 +696,39 @@ impl Game {
|
||||
self.launcher_velocity_milli = 0;
|
||||
}
|
||||
|
||||
fn apply_magnetic_fields(&mut self, old_position: MilliVec, velocity: &mut MilliVec) {
|
||||
for (object_id, min_x, min_y, max_x, max_y) in [
|
||||
(6, 143_000, 421_000, 169_000, 452_000),
|
||||
(153, 1_000, 315_000, 32_000, 389_000),
|
||||
(154, 278_000, 315_000, 312_000, 387_000),
|
||||
] {
|
||||
if !self.object_active[object_id] {
|
||||
continue;
|
||||
}
|
||||
let predicted = old_position.add(*velocity);
|
||||
let sweep_min_x = old_position.x.min(predicted.x);
|
||||
let sweep_max_x = old_position.x.max(predicted.x);
|
||||
let sweep_min_y = old_position.y.min(predicted.y);
|
||||
let sweep_max_y = old_position.y.max(predicted.y);
|
||||
if sweep_max_x < min_x
|
||||
|| sweep_min_x > max_x
|
||||
|| sweep_max_y < min_y
|
||||
|| sweep_min_y > max_y
|
||||
{
|
||||
continue;
|
||||
}
|
||||
velocity.y = velocity.y.min(-3_000);
|
||||
if old_position.add(*velocity).y < min_y {
|
||||
self.object_active[object_id] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn magnetic_field_active(&self, object_id: usize) -> bool {
|
||||
debug_assert!([6, 153, 154].contains(&object_id));
|
||||
self.object_active[object_id]
|
||||
}
|
||||
|
||||
fn next_claw_terminal_frame(&mut self) -> u8 {
|
||||
let value = self.next_random_value();
|
||||
CLAW_TERMINAL_FRAMES[value as usize % CLAW_TERMINAL_FRAMES.len()]
|
||||
@@ -844,7 +868,6 @@ impl Game {
|
||||
self.bonus = 0;
|
||||
self.top_targets.fill(false);
|
||||
self.wheel_holes.fill(false);
|
||||
self.magnets = 0.0;
|
||||
self.tilted = false;
|
||||
self.nudge_meter = 0.0;
|
||||
self.bumper_flash.fill(0.0);
|
||||
@@ -1449,7 +1472,27 @@ mod tests {
|
||||
);
|
||||
assert_eq!(game.player().score, 500);
|
||||
assert_eq!(events, [Event::Target]);
|
||||
assert!((game.magnets - 0.3).abs() < f32::EPSILON);
|
||||
assert!(game.object_active[153]);
|
||||
assert!(!game.object_active[6]);
|
||||
assert!(!game.object_active[154]);
|
||||
|
||||
let mut field_velocity = MilliVec { x: 0, y: 2_015 };
|
||||
game.apply_magnetic_fields(
|
||||
MilliVec {
|
||||
x: 15_000,
|
||||
y: 350_000,
|
||||
},
|
||||
&mut field_velocity,
|
||||
);
|
||||
assert_eq!(field_velocity, MilliVec { x: 0, y: -3_000 });
|
||||
game.apply_magnetic_fields(
|
||||
MilliVec {
|
||||
x: 15_000,
|
||||
y: 317_000,
|
||||
},
|
||||
&mut field_velocity,
|
||||
);
|
||||
assert!(!game.object_active[153]);
|
||||
|
||||
game.check_sensor_objects(
|
||||
MilliVec::from_position(game.ball.position),
|
||||
|
||||
Reference in New Issue
Block a user