Merge pull request '(fix) issues regarding tilemap cache and render' (#23) from dev/fix-issues-with-camera into master
All checks were successful
Intrepid/Prometeu/Runtime/pipeline/head This commit looks good

Reviewed-on: #23
This commit is contained in:
bquarkz 2026-05-01 05:18:33 +00:00
commit d4106253e8

View File

@ -4,7 +4,9 @@ use prometeu_hal::GfxBridge;
use prometeu_hal::glyph::Glyph;
use prometeu_hal::scene_bank::SceneBank;
use prometeu_hal::scene_viewport_cache::SceneViewportCache;
use prometeu_hal::scene_viewport_resolver::{CacheRefreshRequest, SceneViewportResolver};
use prometeu_hal::scene_viewport_resolver::{
CacheRefreshRequest, ResolverUpdate, SceneViewportResolver,
};
use prometeu_hal::sprite::Sprite;
use std::sync::Arc;
@ -257,6 +259,7 @@ impl FrameComposer {
panic!("SCENE runtime invariant broken: active scene without cache/resolver");
};
let update = resolver.update(scene, self.camera_x_px, self.camera_y_px);
Self::sync_cache_windows(cache, &update);
Self::apply_refresh_requests(cache, scene, &update.refresh_requests);
// `FrameComposer` owns only canonical game-frame composition.
// Deferred `gfx.*` primitives are drained later by a separate
@ -334,6 +337,16 @@ impl FrameComposer {
}
}
}
fn sync_cache_windows(cache: &mut SceneViewportCache, update: &ResolverUpdate) {
for request in &update.copy_requests {
cache.move_layer_window_to(
request.layer_index,
request.cache_origin_tile_x,
request.cache_origin_tile_y,
);
}
}
}
#[cfg(test)]
@ -360,6 +373,16 @@ mod tests {
glyph_asset_id: AssetId,
palette_id: u8,
tile_size: TileSize,
) -> SceneBank {
make_scene_grid(glyph_asset_id, palette_id, tile_size, 2, 2)
}
fn make_scene_grid(
glyph_asset_id: AssetId,
palette_id: u8,
tile_size: TileSize,
width: usize,
height: usize,
) -> SceneBank {
let layer = SceneLayer {
active: true,
@ -367,8 +390,8 @@ mod tests {
tile_size,
parallax_factor: ParallaxFactor { x: 1.0, y: 0.5 },
tilemap: TileMap {
width: 2,
height: 2,
width,
height,
tiles: vec![
Tile {
active: true,
@ -376,7 +399,7 @@ mod tests {
flip_x: false,
flip_y: false,
};
4
width * height
],
},
};
@ -768,6 +791,43 @@ mod tests {
assert_eq!(gfx.front_buffer()[0], Color::BLUE.raw());
}
#[test]
fn render_frame_realigns_cache_window_before_refresh_when_camera_moves() {
let banks = Arc::new(MemoryBanks::new());
let scene = Arc::new(make_scene_grid(0, 2, TileSize::Size8, 16, 16));
banks.install_glyph_bank(0, Arc::new(make_glyph_bank(TileSize::Size8, 2, Color::BLUE)));
banks.install_scene_bank(0, Arc::clone(&scene));
let mut frame_composer = FrameComposer::new(
16,
16,
Arc::clone(&banks) as Arc<dyn SceneBankPoolAccess>,
make_glyph_slot_index(&[(0, 0)]),
);
assert!(frame_composer.bind_scene(0));
let mut expected_resolver = FrameComposer::build_scene_runtime(16, 16, &scene).1;
expected_resolver.update(&scene, 0, 0);
let expected_update = expected_resolver.update(&scene, 40, 0);
let mut gfx = Gfx::new(16, 16, Arc::clone(&banks) as Arc<dyn GlyphBankPoolAccess>);
gfx.scene_fade_level = 31;
gfx.hud_fade_level = 31;
frame_composer.render_frame(&mut gfx);
frame_composer.set_camera(40, 0);
frame_composer.render_frame(&mut gfx);
let cache = frame_composer.cache().expect("cache should exist");
assert_eq!(
cache.layers[0].logical_origin(),
(
expected_update.copy_requests[0].cache_origin_tile_x,
expected_update.copy_requests[0].cache_origin_tile_y,
)
);
}
#[test]
fn render_frame_survives_scene_transition_through_unbind_and_rebind() {
let banks = Arc::new(MemoryBanks::new());