mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 16:21:33 +11:00
move static sprite loader into managed oam
This commit is contained in:
parent
ab082c59a1
commit
c03c1664cb
|
@ -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)]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue