move static sprite loader into managed oam

This commit is contained in:
Corwin 2023-04-02 16:34:51 +01:00
parent ab082c59a1
commit c03c1664cb
No known key found for this signature in database
5 changed files with 67 additions and 29 deletions

View file

@ -4,7 +4,7 @@
use agb::{ use agb::{
display::tiled::{TileFormat, TileSet, TileSetting, TiledMap}, display::tiled::{TileFormat, TileSet, TileSetting, TiledMap},
display::{ display::{
object::{Object, Size, Sprite, StaticSpriteLoader}, object::{OAMManager, Object, Size, Sprite, StaticSpriteLoader},
palette16::Palette16, palette16::Palette16,
tiled::RegularBackgroundSize, tiled::RegularBackgroundSize,
HEIGHT, WIDTH, HEIGHT, WIDTH,
@ -74,9 +74,9 @@ fn main(mut gba: agb::Gba) -> ! {
background.show(); background.show();
background.commit(&mut vram); background.commit(&mut vram);
let (object, mut sprites) = gba.display.object.get_managed(); let object = gba.display.object.get_managed();
let sprite = sprites.get_vram_sprite(&CHICKEN_SPRITES[0]); let sprite = object.get_vram_sprite(&CHICKEN_SPRITES[0]);
let mut chicken = Character { let mut chicken = Character {
object: object.add_object(sprite), object: object.add_object(sprite),
position: Vector2D { position: Vector2D {
@ -137,7 +137,7 @@ fn main(mut gba: agb::Gba) -> ! {
} }
restrict_to_screen(&mut chicken); restrict_to_screen(&mut chicken);
update_chicken_object(&mut chicken, &mut sprites, state, frame_count); update_chicken_object(&mut chicken, &object, state, frame_count);
object.commit(); object.commit();
} }
@ -145,7 +145,7 @@ fn main(mut gba: agb::Gba) -> ! {
fn update_chicken_object( fn update_chicken_object(
chicken: &'_ mut Character<'_>, chicken: &'_ mut Character<'_>,
sprites: &mut StaticSpriteLoader, gfx: &OAMManager,
state: State, state: State,
frame_count: u32, frame_count: u32,
) { ) {
@ -158,18 +158,18 @@ fn update_chicken_object(
State::Ground => { State::Ground => {
if chicken.velocity.x.abs() > 1 << 4 { if chicken.velocity.x.abs() > 1 << 4 {
chicken.object.set_sprite( chicken.object.set_sprite(
sprites.get_vram_sprite(&CHICKEN_SPRITES[frame_ranger(frame_count, 1, 3, 10)]), gfx.get_vram_sprite(&CHICKEN_SPRITES[frame_ranger(frame_count, 1, 3, 10)]),
); );
} else { } else {
chicken chicken
.object .object
.set_sprite(sprites.get_vram_sprite(&CHICKEN_SPRITES[0])); .set_sprite(gfx.get_vram_sprite(&CHICKEN_SPRITES[0]));
} }
} }
State::Upwards => {} State::Upwards => {}
State::Flapping => { State::Flapping => {
chicken.object.set_sprite( chicken.object.set_sprite(
sprites.get_vram_sprite(&CHICKEN_SPRITES[frame_ranger(frame_count, 4, 5, 5)]), gfx.get_vram_sprite(&CHICKEN_SPRITES[frame_ranger(frame_count, 4, 5, 5)]),
); );
} }
} }

View file

@ -3,7 +3,7 @@
extern crate alloc; extern crate alloc;
use agb::display::object::{Graphics, OAMManager, Sprite, StaticSpriteLoader, TagMap}; use agb::display::object::{Graphics, OAMManager, Sprite, TagMap};
use alloc::vec::Vec; use alloc::vec::Vec;
const GRAPHICS: &Graphics = agb::include_aseprite!( const GRAPHICS: &Graphics = agb::include_aseprite!(
@ -15,13 +15,13 @@ const GRAPHICS: &Graphics = agb::include_aseprite!(
const SPRITES: &[Sprite] = GRAPHICS.sprites(); const SPRITES: &[Sprite] = GRAPHICS.sprites();
const TAG_MAP: &TagMap = GRAPHICS.tags(); const TAG_MAP: &TagMap = GRAPHICS.tags();
fn all_sprites(gfx: &OAMManager, sprites: &mut StaticSpriteLoader) { fn all_sprites(gfx: &OAMManager) {
let mut input = agb::input::ButtonController::new(); let mut input = agb::input::ButtonController::new();
let mut objs = Vec::new(); let mut objs = Vec::new();
for y in 0..9 { for y in 0..9 {
for x in 0..14 { for x in 0..14 {
let mut obj = gfx.add_object(sprites.get_vram_sprite(&SPRITES[0])); let mut obj = gfx.add_object_static_sprite(&SPRITES[0]);
obj.show(); obj.show();
obj.set_position((x * 16 + 8, y * 16 + 8).into()); obj.set_position((x * 16 + 8, y * 16 + 8).into());
objs.push(obj); objs.push(obj);
@ -48,14 +48,14 @@ fn all_sprites(gfx: &OAMManager, sprites: &mut StaticSpriteLoader) {
image %= SPRITES.len(); image %= SPRITES.len();
for (i, obj) in objs.iter_mut().enumerate() { for (i, obj) in objs.iter_mut().enumerate() {
let this_image = (image + i) % SPRITES.len(); let this_image = (image + i) % SPRITES.len();
obj.set_sprite(sprites.get_vram_sprite(&SPRITES[this_image])); obj.set_sprite(gfx.get_vram_sprite(&SPRITES[this_image]));
} }
gfx.commit(); gfx.commit();
} }
} }
} }
fn all_tags(gfx: &OAMManager, sprites: &mut StaticSpriteLoader) { fn all_tags(gfx: &OAMManager) {
let mut input = agb::input::ButtonController::new(); let mut input = agb::input::ButtonController::new();
let mut objs = Vec::new(); let mut objs = Vec::new();
@ -65,7 +65,7 @@ fn all_tags(gfx: &OAMManager, sprites: &mut StaticSpriteLoader) {
let sprite = v.sprite(0); let sprite = v.sprite(0);
let (size_x, size_y) = sprite.size().to_width_height(); let (size_x, size_y) = sprite.size().to_width_height();
let (size_x, size_y) = (size_x as i32, size_y as i32); let (size_x, size_y) = (size_x as i32, size_y as i32);
let mut obj = gfx.add_object(sprites.get_vram_sprite(sprite)); let mut obj = gfx.add_object_static_sprite(sprite);
obj.show(); obj.show();
obj.set_position((x * 32 + 16 - size_x / 2, y * 32 + 16 - size_y / 2).into()); obj.set_position((x * 32 + 16 - size_x / 2, y * 32 + 16 - size_y / 2).into());
objs.push((obj, v)); objs.push((obj, v));
@ -90,7 +90,7 @@ fn all_tags(gfx: &OAMManager, sprites: &mut StaticSpriteLoader) {
if count % 5 == 0 { if count % 5 == 0 {
image += 1; image += 1;
for (obj, tag) in objs.iter_mut() { for (obj, tag) in objs.iter_mut() {
obj.set_sprite(sprites.get_vram_sprite(tag.animation_sprite(image))); obj.set_sprite(gfx.get_vram_sprite(tag.animation_sprite(image)));
} }
gfx.commit(); gfx.commit();
} }
@ -99,12 +99,12 @@ fn all_tags(gfx: &OAMManager, sprites: &mut StaticSpriteLoader) {
#[agb::entry] #[agb::entry]
fn main(mut gba: agb::Gba) -> ! { fn main(mut gba: agb::Gba) -> ! {
let (gfx, mut ssl) = gba.display.object.get_managed(); let gfx = gba.display.object.get_managed();
loop { loop {
all_tags(&gfx, &mut ssl); all_tags(&gfx);
gfx.commit(); gfx.commit();
all_sprites(&gfx, &mut ssl); all_sprites(&gfx);
gfx.commit(); gfx.commit();
} }
} }

View file

@ -89,9 +89,9 @@ impl ObjectDistribution {
(UnmanagedOAM::new(), StaticSpriteLoader::new()) (UnmanagedOAM::new(), StaticSpriteLoader::new())
} }
pub fn get_managed(&mut self) -> (OAMManager<'_>, StaticSpriteLoader) { pub fn get_managed(&mut self) -> OAMManager<'_> {
unsafe { initilise_oam() }; unsafe { initilise_oam() };
(OAMManager::new(), StaticSpriteLoader::new()) OAMManager::new()
} }
} }

View file

@ -4,11 +4,12 @@ use core::{
}; };
use agb_fixnum::Vector2D; use agb_fixnum::Vector2D;
use alloc::vec::Vec;
use slotmap::{new_key_type, SlotMap}; use slotmap::{new_key_type, SlotMap};
use crate::display::Priority; use crate::{display::Priority, sync::Static};
use super::{AffineMode, SpriteVram, UnmanagedOAM, UnmanagedObject}; use super::{AffineMode, Sprite, SpriteVram, StaticSpriteLoader, UnmanagedOAM, UnmanagedObject};
new_key_type! {struct ObjectKey; } new_key_type! {struct ObjectKey; }
@ -26,6 +27,7 @@ struct ObjectItem {
struct Store { struct Store {
store: UnsafeCell<slotmap::SlotMap<ObjectKey, ObjectItem>>, store: UnsafeCell<slotmap::SlotMap<ObjectKey, ObjectItem>>,
removal_list: UnsafeCell<Vec<ObjectKey>>,
first_z: Cell<Option<ObjectKey>>, first_z: Cell<Option<ObjectKey>>,
} }
@ -111,12 +113,24 @@ impl Store {
} }
fn remove_object(&self, object: ObjectKey) { fn remove_object(&self, object: ObjectKey) {
remove_from_linked_list(self, object);
let data = unsafe { &mut *self.store.get() }; let data = unsafe { &mut *self.store.get() };
data.remove(object); data.remove(object);
} }
fn remove_all_in_removal_list(&self) {
let removal_list = unsafe { &mut *self.removal_list.get() };
for object in removal_list.drain(..) {
self.remove_object(object);
}
}
fn mark_for_removal(&self, object: ObjectKey) {
let removal_list = unsafe { &mut *self.removal_list.get() };
removal_list.push(object);
remove_from_linked_list(self, object);
}
fn get_object(&self, key: ObjectKey) -> &ObjectItem { fn get_object(&self, key: ObjectKey) -> &ObjectItem {
&(unsafe { &*self.store.get() }[key]) &(unsafe { &*self.store.get() }[key])
} }
@ -125,6 +139,7 @@ impl Store {
pub struct OAMManager<'gba> { pub struct OAMManager<'gba> {
phantom: PhantomData<&'gba ()>, phantom: PhantomData<&'gba ()>,
object_store: Store, object_store: Store,
sprite_loader: UnsafeCell<StaticSpriteLoader>,
} }
impl OAMManager<'_> { impl OAMManager<'_> {
@ -133,16 +148,29 @@ impl OAMManager<'_> {
phantom: PhantomData, phantom: PhantomData,
object_store: Store { object_store: Store {
store: UnsafeCell::new(SlotMap::with_key()), store: UnsafeCell::new(SlotMap::with_key()),
removal_list: UnsafeCell::new(Vec::new()),
first_z: Cell::new(None), first_z: Cell::new(None),
}, },
sprite_loader: UnsafeCell::new(StaticSpriteLoader::new()),
} }
} }
pub fn do_work_with_sprite_loader<C, T>(&self, c: C) -> T
where
C: Fn(&mut StaticSpriteLoader) -> T,
{
let sprite_loader = unsafe { &mut *self.sprite_loader.get() };
c(sprite_loader)
}
pub fn commit(&self) { pub fn commit(&self) {
let mut count = 0; let mut count = 0;
let mut unmanaged = UnmanagedOAM::new(); let mut unmanaged = UnmanagedOAM::new();
// do interactions with OAM
for (object, mut slot) in unsafe { self.object_store.iter() } for (object, mut slot) in unsafe { self.object_store.iter() }
.map(|item| unsafe { &*item.object.get() }) .map(|item| unsafe { &*item.object.get() })
.filter(|object| object.is_visible()) .filter(|object| object.is_visible())
@ -151,16 +179,26 @@ impl OAMManager<'_> {
slot.set(object); slot.set(object);
count += 1; count += 1;
} }
crate::println!("{}", count);
unmanaged.clear_from(count); unmanaged.clear_from(count);
// finished OAM interactions
self.object_store.remove_all_in_removal_list();
self.do_work_with_sprite_loader(StaticSpriteLoader::garbage_collect);
} }
pub fn add_object(&self, sprite: SpriteVram) -> Object<'_> { pub fn add_object(&self, sprite: SpriteVram) -> Object<'_> {
self.object_store self.object_store
.insert_object(UnmanagedObject::new(sprite)) .insert_object(UnmanagedObject::new(sprite))
} }
pub fn get_vram_sprite(&self, sprite: &'static Sprite) -> SpriteVram {
self.do_work_with_sprite_loader(|sprite_loader| sprite_loader.get_vram_sprite(sprite))
}
pub fn add_object_static_sprite(&self, sprite: &'static Sprite) -> Object<'_> {
self.add_object(self.get_vram_sprite(sprite))
}
} }
pub struct Object<'controller> { pub struct Object<'controller> {
@ -170,7 +208,7 @@ pub struct Object<'controller> {
impl Drop for Object<'_> { impl Drop for Object<'_> {
fn drop(&mut self) { fn drop(&mut self) {
self.store.remove_object(self.me); self.store.mark_for_removal(self.me);
} }
} }

View file

@ -231,7 +231,7 @@ impl StaticSpriteLoader {
} }
} }
fn gc(&mut self) { pub fn garbage_collect(&mut self) {
self.static_sprite_map self.static_sprite_map
.retain(|_, v| Weak::strong_count(v) != 0); .retain(|_, v| Weak::strong_count(v) != 0);
self.static_palette_map self.static_palette_map