From 3a913f142ad2c2379519d1b360fc3fa0bd54f355 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Mon, 14 Feb 2022 21:53:09 +0000 Subject: [PATCH] Remove pop while loading a level --- agb/src/display/background.rs | 54 ++++++++++++++++--- .../the-hat-chooses-the-wizard/src/main.rs | 49 +++++++---------- 2 files changed, 68 insertions(+), 35 deletions(-) diff --git a/agb/src/display/background.rs b/agb/src/display/background.rs index c017dde7..ecc5309f 100644 --- a/agb/src/display/background.rs +++ b/agb/src/display/background.rs @@ -458,6 +458,14 @@ pub struct InfiniteScrolledMap<'a> { current_pos: Vector2D, offset: Vector2D, + + copied_up_to: i32, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum PartialUpdateStatus { + Done, + Continue, } impl<'a> InfiniteScrolledMap<'a> { @@ -470,10 +478,26 @@ impl<'a> InfiniteScrolledMap<'a> { get_tile, current_pos: (0, 0).into(), offset: (0, 0).into(), + copied_up_to: 0, } } - pub fn init(&mut self, vram: &mut VRamManager, pos: Vector2D) { + pub fn init( + &mut self, + vram: &mut VRamManager, + pos: Vector2D, + between_updates: Box, + ) { + while self.init_partial(vram, pos) != PartialUpdateStatus::Done { + between_updates(); + } + } + + pub fn init_partial( + &mut self, + vram: &mut VRamManager, + pos: Vector2D, + ) -> PartialUpdateStatus { self.current_pos = pos; let x_start = div_floor(self.current_pos.x, 8); @@ -492,29 +516,45 @@ impl<'a> InfiniteScrolledMap<'a> { self.map.set_scroll_pos(offset_scroll); self.offset = (x_start, y_start).into(); - for (y_idx, y) in (y_start..y_end).enumerate() { + let copy_from = self.copied_up_to; + const ROWS_TO_COPY: i32 = 2; + + for (y_idx, y) in + ((y_start + copy_from)..(y_end.min(y_start + copy_from + ROWS_TO_COPY))).enumerate() + { for (x_idx, x) in (x_start..x_end).enumerate() { let pos = (x, y).into(); let (tile_set_ref, tile_setting) = (self.get_tile)(pos); self.map.set_tile( vram, - (x_idx as u16, y_idx as u16).into(), + (x_idx as u16, (y_idx + copy_from as usize) as u16).into(), tile_set_ref, tile_setting, ); } } + + if copy_from + ROWS_TO_COPY >= y_end - y_start { + self.copied_up_to = 0; + PartialUpdateStatus::Done + } else { + self.copied_up_to = copy_from + ROWS_TO_COPY; + PartialUpdateStatus::Continue + } } - pub fn set_pos(&mut self, vram: &mut VRamManager, new_pos: Vector2D) { + pub fn set_pos( + &mut self, + vram: &mut VRamManager, + new_pos: Vector2D, + ) -> PartialUpdateStatus { let old_pos = self.current_pos; let difference = new_pos - old_pos; if difference.x.abs() > 10 * 8 || difference.y.abs() > 10 * 8 { - self.init(vram, new_pos); - return; + return self.init_partial(vram, new_pos); } self.current_pos = new_pos; @@ -599,6 +639,8 @@ impl<'a> InfiniteScrolledMap<'a> { .into(); self.map.set_scroll_pos(new_scroll); + + PartialUpdateStatus::Done } pub fn show(&mut self) { diff --git a/examples/the-hat-chooses-the-wizard/src/main.rs b/examples/the-hat-chooses-the-wizard/src/main.rs index 5904bbc2..c7f08fcd 100644 --- a/examples/the-hat-chooses-the-wizard/src/main.rs +++ b/examples/the-hat-chooses-the-wizard/src/main.rs @@ -5,7 +5,9 @@ extern crate alloc; use agb::{ display::{ - background::{InfiniteScrolledMap, TileFormat, TileSet, TileSetting, VRamManager}, + background::{ + InfiniteScrolledMap, PartialUpdateStatus, TileFormat, TileSet, TileSetting, VRamManager, + }, object::{ObjectControl, ObjectStandard, Size}, Priority, HEIGHT, WIDTH, }, @@ -285,12 +287,12 @@ impl<'a, 'b> Map<'a, 'b> { self.foreground.commit(); } - pub fn init_background(&mut self, vram: &mut VRamManager) { - self.background.init(vram, self.position.floor()); + pub fn init_background(&mut self, vram: &mut VRamManager) -> PartialUpdateStatus { + self.background.init_partial(vram, self.position.floor()) } - pub fn init_foreground(&mut self, vram: &mut VRamManager) { - self.foreground.init(vram, self.position.floor()); + pub fn init_foreground(&mut self, vram: &mut VRamManager) -> PartialUpdateStatus { + self.foreground.init_partial(vram, self.position.floor()) } } @@ -885,32 +887,21 @@ fn main(mut agb: agb::Gba) -> ! { agb::input::ButtonController::new(), ); - music_box.before_frame(&mut mixer); - mixer.frame(); - vblank.wait_for_vblank(); - mixer.after_vblank(); - let (before_init_cycles, before_init_cycles_2) = - (timer.get_value(), timer_cascade.get_value()); + while level.background.init_background(&mut vram) != PartialUpdateStatus::Done { + music_box.before_frame(&mut mixer); + mixer.frame(); + vblank.wait_for_vblank(); + mixer.after_vblank(); + } - level.background.init_background(&mut vram); + while level.background.init_foreground(&mut vram) != PartialUpdateStatus::Done { + music_box.before_frame(&mut mixer); + mixer.frame(); + vblank.wait_for_vblank(); + mixer.after_vblank(); + } - let (after_init_cycles, after_init_cycles_2) = - (timer.get_value(), timer_cascade.get_value()); - let after_init_cycles = - (after_init_cycles as u32) | ((after_init_cycles_2 as u32) << 16); - let before_init_cycles = - (before_init_cycles as u32) | ((before_init_cycles_2 as u32) << 16); - - music_box.before_frame(&mut mixer); - mixer.frame(); - agb::println!("cycles for init {}", after_init_cycles - before_init_cycles); - vblank.wait_for_vblank(); - - mixer.after_vblank(); - - level.background.init_foreground(&mut vram); - - for _ in 0..60 { + for _ in 0..20 { music_box.before_frame(&mut mixer); mixer.frame(); vblank.wait_for_vblank();