fix(game): restore the 281-frame panel sequence
Replace the immediate five-hole cleanup with the original 281-callback panel state machine. Suspend physics, clear contact/item state at the recovered boundaries, and emit WAVE 2013, WAVE 2012, and stop events at frames 1/45/58/66/129/159/222/230/238 before resuming after cleanup. Decode DAT600's four AND/OR mask-image pairs into transparent native textures and render all nine phase formulas with the original source rectangles, destination offsets, variable heights, and opaque wheel copies. Add a `panel` simulation scenario for deterministic trace and framebuffer validation. Test Plan: - `cargo test --all-targets` -- passed, 72 tests - `cargo clippy --all-targets -- -D warnings` -- passed - `rumdl check CHANGELOG.md README.md RECONSTRUCTION.md` -- passed - rendered panel frames 1, 66, 159, 238, and completion -- visually verified - `git diff --cached --check` -- passed
This commit is contained in:
+50
-2
@@ -1,5 +1,5 @@
|
||||
use macroquad::{
|
||||
audio::{PlaySoundParams, Sound, load_sound_from_bytes, play_sound},
|
||||
audio::{PlaySoundParams, Sound, load_sound_from_bytes, play_sound, stop_sound},
|
||||
prelude::{FilterMode, Image, Texture2D},
|
||||
};
|
||||
|
||||
@@ -11,6 +11,10 @@ pub struct Assets {
|
||||
pub media: [Texture2D; 4],
|
||||
pub diamond: [Texture2D; 9],
|
||||
pub wheel: Texture2D,
|
||||
pub panel_pair_narrow_a: Texture2D,
|
||||
pub panel_pair_narrow_b: Texture2D,
|
||||
pub panel_pair_wide_a: Texture2D,
|
||||
pub panel_pair_wide_b: Texture2D,
|
||||
pub robot: Texture2D,
|
||||
pub plunger: Texture2D,
|
||||
pub ball: Texture2D,
|
||||
@@ -48,7 +52,12 @@ impl Assets {
|
||||
texture(include_bytes!("../assets/original/images/dat_00808.png")),
|
||||
texture(include_bytes!("../assets/original/images/dat_00809.png")),
|
||||
];
|
||||
let wheel = texture(include_bytes!("../assets/original/images/dat_00600.png"));
|
||||
let wheel_bytes = include_bytes!("../assets/original/images/dat_00600.png");
|
||||
let wheel = texture(wheel_bytes);
|
||||
let panel_pair_narrow_a = masked_atlas_pair(wheel_bytes, 0, 45, 45, 90);
|
||||
let panel_pair_narrow_b = masked_atlas_pair(wheel_bytes, 90, 135, 45, 90);
|
||||
let panel_pair_wide_a = masked_atlas_pair(wheel_bytes, 271, 362, 91, 90);
|
||||
let panel_pair_wide_b = masked_atlas_pair(wheel_bytes, 453, 362, 91, 90);
|
||||
let robot = texture(include_bytes!("../assets/original/images/dat_00900.png"));
|
||||
let plunger = texture(include_bytes!("../assets/original/images/dat_00901.png"));
|
||||
let ball = masked_texture(
|
||||
@@ -139,6 +148,10 @@ impl Assets {
|
||||
media,
|
||||
diamond,
|
||||
wheel,
|
||||
panel_pair_narrow_a,
|
||||
panel_pair_narrow_b,
|
||||
panel_pair_wide_a,
|
||||
panel_pair_wide_b,
|
||||
robot,
|
||||
plunger,
|
||||
ball,
|
||||
@@ -161,6 +174,12 @@ impl Assets {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stop_all_sounds(&self) {
|
||||
for (_, sound) in &self.sounds {
|
||||
stop_sound(sound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn texture(bytes: &[u8]) -> Texture2D {
|
||||
@@ -200,3 +219,32 @@ fn monochrome_texture(bytes: &[u8]) -> Texture2D {
|
||||
texture.set_filter(FilterMode::Nearest);
|
||||
texture
|
||||
}
|
||||
|
||||
fn masked_atlas_pair(
|
||||
bytes: &[u8],
|
||||
image_x: usize,
|
||||
mask_x: usize,
|
||||
width: usize,
|
||||
height: usize,
|
||||
) -> Texture2D {
|
||||
let atlas = Image::from_file_with_format(bytes, None).expect("embedded DAT600 must decode");
|
||||
let atlas_width = usize::from(atlas.width);
|
||||
let mut output = Image {
|
||||
bytes: vec![0; width * height * 4],
|
||||
width: u16::try_from(width).unwrap_or(0),
|
||||
height: u16::try_from(height).unwrap_or(0),
|
||||
};
|
||||
for y in 0..height {
|
||||
for x in 0..width {
|
||||
let output_index = (y * width + x) * 4;
|
||||
let image_index = ((y + 90) * atlas_width + image_x + x) * 4;
|
||||
let mask_index = ((y + 90) * atlas_width + mask_x + x) * 4;
|
||||
output.bytes[output_index..output_index + 3]
|
||||
.copy_from_slice(&atlas.bytes[image_index..image_index + 3]);
|
||||
output.bytes[output_index + 3] = u8::MAX - atlas.bytes[mask_index];
|
||||
}
|
||||
}
|
||||
let texture = Texture2D::from_image(&output);
|
||||
texture.set_filter(FilterMode::Nearest);
|
||||
texture
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user