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