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::{
display::tiled::{TileFormat, TileSet, TileSetting, TiledMap},
display::{
object::{Object, Size, Sprite, StaticSpriteLoader},
object::{OAMManager, Object, Size, Sprite, StaticSpriteLoader},
palette16::Palette16,
tiled::RegularBackgroundSize,
HEIGHT, WIDTH,
@ -74,9 +74,9 @@ fn main(mut gba: agb::Gba) -> ! {
background.show();
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 {
object: object.add_object(sprite),
position: Vector2D {
@ -137,7 +137,7 @@ fn main(mut gba: agb::Gba) -> ! {
}
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();
}
@ -145,7 +145,7 @@ fn main(mut gba: agb::Gba) -> ! {
fn update_chicken_object(
chicken: &'_ mut Character<'_>,
sprites: &mut StaticSpriteLoader,
gfx: &OAMManager,
state: State,
frame_count: u32,
) {
@ -158,18 +158,18 @@ fn update_chicken_object(
State::Ground => {
if chicken.velocity.x.abs() > 1 << 4 {
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 {
chicken
.object
.set_sprite(sprites.get_vram_sprite(&CHICKEN_SPRITES[0]));
.set_sprite(gfx.get_vram_sprite(&CHICKEN_SPRITES[0]));
}
}
State::Upwards => {}
State::Flapping => {
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;
use agb::display::object::{Graphics, OAMManager, Sprite, StaticSpriteLoader, TagMap};
use agb::display::object::{Graphics, OAMManager, Sprite, TagMap};
use alloc::vec::Vec;
const GRAPHICS: &Graphics = agb::include_aseprite!(
@ -15,13 +15,13 @@ const GRAPHICS: &Graphics = agb::include_aseprite!(
const SPRITES: &[Sprite] = GRAPHICS.sprites();
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 objs = Vec::new();
for y in 0..9 {
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.set_position((x * 16 + 8, y * 16 + 8).into());
objs.push(obj);
@ -48,14 +48,14 @@ fn all_sprites(gfx: &OAMManager, sprites: &mut StaticSpriteLoader) {
image %= SPRITES.len();
for (i, obj) in objs.iter_mut().enumerate() {
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();
}
}
}
fn all_tags(gfx: &OAMManager, sprites: &mut StaticSpriteLoader) {
fn all_tags(gfx: &OAMManager) {
let mut input = agb::input::ButtonController::new();
let mut objs = Vec::new();
@ -65,7 +65,7 @@ fn all_tags(gfx: &OAMManager, sprites: &mut StaticSpriteLoader) {
let sprite = v.sprite(0);
let (size_x, size_y) = sprite.size().to_width_height();
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.set_position((x * 32 + 16 - size_x / 2, y * 32 + 16 - size_y / 2).into());
objs.push((obj, v));
@ -90,7 +90,7 @@ fn all_tags(gfx: &OAMManager, sprites: &mut StaticSpriteLoader) {
if count % 5 == 0 {
image += 1;
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();
}
@ -99,12 +99,12 @@ fn all_tags(gfx: &OAMManager, sprites: &mut StaticSpriteLoader) {
#[agb::entry]
fn main(mut gba: agb::Gba) -> ! {
let (gfx, mut ssl) = gba.display.object.get_managed();
let gfx = gba.display.object.get_managed();
loop {
all_tags(&gfx, &mut ssl);
all_tags(&gfx);
gfx.commit();
all_sprites(&gfx, &mut ssl);
all_sprites(&gfx);
gfx.commit();
}
}

View file

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

View file

@ -4,11 +4,12 @@ use core::{
};
use agb_fixnum::Vector2D;
use alloc::vec::Vec;
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; }
@ -26,6 +27,7 @@ struct ObjectItem {
struct Store {
store: UnsafeCell<slotmap::SlotMap<ObjectKey, ObjectItem>>,
removal_list: UnsafeCell<Vec<ObjectKey>>,
first_z: Cell<Option<ObjectKey>>,
}
@ -111,12 +113,24 @@ impl Store {
}
fn remove_object(&self, object: ObjectKey) {
remove_from_linked_list(self, object);
let data = unsafe { &mut *self.store.get() };
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 {
&(unsafe { &*self.store.get() }[key])
}
@ -125,6 +139,7 @@ impl Store {
pub struct OAMManager<'gba> {
phantom: PhantomData<&'gba ()>,
object_store: Store,
sprite_loader: UnsafeCell<StaticSpriteLoader>,
}
impl OAMManager<'_> {
@ -133,16 +148,29 @@ impl OAMManager<'_> {
phantom: PhantomData,
object_store: Store {
store: UnsafeCell::new(SlotMap::with_key()),
removal_list: UnsafeCell::new(Vec::new()),
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) {
let mut count = 0;
let mut unmanaged = UnmanagedOAM::new();
// do interactions with OAM
for (object, mut slot) in unsafe { self.object_store.iter() }
.map(|item| unsafe { &*item.object.get() })
.filter(|object| object.is_visible())
@ -151,16 +179,26 @@ impl OAMManager<'_> {
slot.set(object);
count += 1;
}
crate::println!("{}", 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<'_> {
self.object_store
.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> {
@ -170,7 +208,7 @@ pub struct Object<'controller> {
impl Drop for Object<'_> {
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
.retain(|_, v| Weak::strong_count(v) != 0);
self.static_palette_map