mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-24 08:41:34 +11:00
nicer way of using mutable backing storages
This commit is contained in:
parent
d6b388e1d6
commit
7798f4c95f
|
@ -3,7 +3,7 @@
|
|||
|
||||
extern crate agb;
|
||||
use agb::{
|
||||
display::{object::ObjectStandard, HEIGHT, WIDTH},
|
||||
display::{object::ObjectStandard, tiled0::Map, HEIGHT, WIDTH},
|
||||
input::Button,
|
||||
};
|
||||
use core::convert::TryInto;
|
||||
|
@ -52,11 +52,7 @@ pub fn main() -> ! {
|
|||
gfx.set_background_tilemap(0, &MAP_TILES);
|
||||
|
||||
let mut background = gfx.get_background().unwrap();
|
||||
background.set_map(agb::display::tiled0::Map {
|
||||
store: MAP_MAP.as_ref(),
|
||||
dimensions: (32_u32, 32_u32).into(),
|
||||
default: 0,
|
||||
});
|
||||
background.set_map(Map::new(&MAP_MAP, (32_u32, 32_u32).into(), 0));
|
||||
background.show();
|
||||
background.commit();
|
||||
|
||||
|
|
|
@ -2,9 +2,8 @@ use crate::display::tiled0::Tiled0;
|
|||
|
||||
crate::include_gfx!("gfx/agb_logo.toml");
|
||||
|
||||
use super::tiled0::Map;
|
||||
|
||||
pub fn display_logo(gfx: &mut Tiled0) {
|
||||
use super::tiled0::Map;
|
||||
gfx.set_background_palettes(agb_logo::test_logo.palettes);
|
||||
gfx.set_background_tilemap(0, agb_logo::test_logo.tiles);
|
||||
|
||||
|
@ -16,11 +15,7 @@ pub fn display_logo(gfx: &mut Tiled0) {
|
|||
entries[tile_id as usize] = tile_id | (palette_entry << 12);
|
||||
}
|
||||
|
||||
back.set_map(Map {
|
||||
store: entries.as_ref(),
|
||||
dimensions: (30_u32, 20_u32).into(),
|
||||
default: 0,
|
||||
});
|
||||
back.set_map(Map::new(&entries, (30_u32, 20_u32).into(), 0));
|
||||
back.show();
|
||||
}
|
||||
|
||||
|
|
|
@ -30,30 +30,86 @@ pub enum BackgroundSize {
|
|||
S64x64 = 3,
|
||||
}
|
||||
|
||||
pub trait MapStorage: Deref<Target = [u16]> {}
|
||||
impl MapStorage for &[u16] {}
|
||||
impl MapStorage for &mut [u16] {}
|
||||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
enum Mutability {
|
||||
Immutable,
|
||||
Mutable,
|
||||
}
|
||||
|
||||
struct MapStorage<'a> {
|
||||
s: *const [u16],
|
||||
mutability: Mutability,
|
||||
_phantom: core::marker::PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
impl<'a> Index<usize> for MapStorage<'a> {
|
||||
type Output = u16;
|
||||
fn index(&self, index: usize) -> &Self::Output {
|
||||
&self.get()[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MapStorage<'a> {
|
||||
fn new(store: &[u16]) -> MapStorage {
|
||||
MapStorage {
|
||||
s: store as *const _,
|
||||
mutability: Mutability::Immutable,
|
||||
_phantom: core::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
fn new_mutable(store: &mut [u16]) -> MapStorage {
|
||||
MapStorage {
|
||||
s: store as *const _,
|
||||
mutability: Mutability::Mutable,
|
||||
_phantom: core::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
fn get(&self) -> &[u16] {
|
||||
unsafe { &*self.s }
|
||||
}
|
||||
fn get_mut(&mut self) -> &mut [u16] {
|
||||
assert!(
|
||||
self.mutability == Mutability::Mutable,
|
||||
"backing storage must be mutable in order to get internal storage mutably"
|
||||
);
|
||||
unsafe { &mut *(self.s as *mut _) }
|
||||
}
|
||||
}
|
||||
|
||||
/// The map background is the method of drawing game maps to the screen. It
|
||||
/// automatically handles copying the correct portion of a provided map to the
|
||||
/// assigned block depending on given coordinates.
|
||||
pub struct Background<S: MapStorage> {
|
||||
pub struct Background<'a> {
|
||||
background: u8,
|
||||
block: u8,
|
||||
commited_position: Vector2D<i32>,
|
||||
shadowed_position: Vector2D<i32>,
|
||||
poisoned: bool,
|
||||
shadowed_register: u16,
|
||||
map: Option<Map<S>>,
|
||||
map: Option<Map<'a>>,
|
||||
}
|
||||
|
||||
pub struct Map<S: MapStorage> {
|
||||
pub store: S,
|
||||
pub struct Map<'a> {
|
||||
store: MapStorage<'a>,
|
||||
pub dimensions: Vector2D<u32>,
|
||||
pub default: u16,
|
||||
}
|
||||
|
||||
impl<'a, S: MapStorage> Map<S> {
|
||||
impl<'a> Map<'a> {
|
||||
pub fn new(map: &[u16], dimensions: Vector2D<u32>, default: u16) -> Map {
|
||||
Map {
|
||||
store: MapStorage::new(map),
|
||||
dimensions,
|
||||
default,
|
||||
}
|
||||
}
|
||||
pub fn new_mutable(map: &mut [u16], dimensions: Vector2D<u32>, default: u16) -> Map {
|
||||
Map {
|
||||
store: MapStorage::new_mutable(map),
|
||||
dimensions,
|
||||
default,
|
||||
}
|
||||
}
|
||||
fn get_position(&self, x: i32, y: i32) -> u16 {
|
||||
if x < 0 || x as u32 >= self.dimensions.x {
|
||||
self.default
|
||||
|
@ -63,10 +119,16 @@ impl<'a, S: MapStorage> Map<S> {
|
|||
self.store[y as usize * self.dimensions.x as usize + x as usize]
|
||||
}
|
||||
}
|
||||
pub fn get_store(&self) -> &[u16] {
|
||||
self.store.get()
|
||||
}
|
||||
pub fn get_mutable_store(&mut self) -> &mut [u16] {
|
||||
self.store.get_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: MapStorage> Background<S> {
|
||||
unsafe fn new(background: u8, block: u8) -> Background<S> {
|
||||
impl<'a> Background<'a> {
|
||||
unsafe fn new(background: u8, block: u8) -> Background<'a> {
|
||||
let mut b = Background {
|
||||
background,
|
||||
block,
|
||||
|
@ -135,12 +197,12 @@ impl<'a, S: MapStorage> Background<S> {
|
|||
self.shadowed_position = position;
|
||||
}
|
||||
|
||||
pub fn get_map(&mut self) -> Option<&mut Map<S>> {
|
||||
pub fn get_map(&mut self) -> Option<&mut Map<'a>> {
|
||||
self.poisoned = true;
|
||||
self.map.as_mut()
|
||||
}
|
||||
|
||||
pub fn set_map(&mut self, map: Map<S>) {
|
||||
pub fn set_map(&mut self, map: Map<'a>) {
|
||||
self.poisoned = true;
|
||||
self.map = Some(map);
|
||||
}
|
||||
|
@ -266,7 +328,7 @@ impl Tiled0 {
|
|||
}
|
||||
|
||||
/// Gets a map background if possible and assigns an unused block to it.
|
||||
pub fn get_background<S: MapStorage>(&mut self) -> Result<Background<S>, &'static str> {
|
||||
pub fn get_background(&mut self) -> Result<Background, &'static str> {
|
||||
if self.num_backgrounds >= 4 {
|
||||
return Err("too many backgrounds created, maximum is 4");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue