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;
|
extern crate agb;
|
||||||
use agb::{
|
use agb::{
|
||||||
display::{object::ObjectStandard, HEIGHT, WIDTH},
|
display::{object::ObjectStandard, tiled0::Map, HEIGHT, WIDTH},
|
||||||
input::Button,
|
input::Button,
|
||||||
};
|
};
|
||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
|
@ -52,11 +52,7 @@ pub fn main() -> ! {
|
||||||
gfx.set_background_tilemap(0, &MAP_TILES);
|
gfx.set_background_tilemap(0, &MAP_TILES);
|
||||||
|
|
||||||
let mut background = gfx.get_background().unwrap();
|
let mut background = gfx.get_background().unwrap();
|
||||||
background.set_map(agb::display::tiled0::Map {
|
background.set_map(Map::new(&MAP_MAP, (32_u32, 32_u32).into(), 0));
|
||||||
store: MAP_MAP.as_ref(),
|
|
||||||
dimensions: (32_u32, 32_u32).into(),
|
|
||||||
default: 0,
|
|
||||||
});
|
|
||||||
background.show();
|
background.show();
|
||||||
background.commit();
|
background.commit();
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,8 @@ use crate::display::tiled0::Tiled0;
|
||||||
|
|
||||||
crate::include_gfx!("gfx/agb_logo.toml");
|
crate::include_gfx!("gfx/agb_logo.toml");
|
||||||
|
|
||||||
use super::tiled0::Map;
|
|
||||||
|
|
||||||
pub fn display_logo(gfx: &mut Tiled0) {
|
pub fn display_logo(gfx: &mut Tiled0) {
|
||||||
|
use super::tiled0::Map;
|
||||||
gfx.set_background_palettes(agb_logo::test_logo.palettes);
|
gfx.set_background_palettes(agb_logo::test_logo.palettes);
|
||||||
gfx.set_background_tilemap(0, agb_logo::test_logo.tiles);
|
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);
|
entries[tile_id as usize] = tile_id | (palette_entry << 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
back.set_map(Map {
|
back.set_map(Map::new(&entries, (30_u32, 20_u32).into(), 0));
|
||||||
store: entries.as_ref(),
|
|
||||||
dimensions: (30_u32, 20_u32).into(),
|
|
||||||
default: 0,
|
|
||||||
});
|
|
||||||
back.show();
|
back.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,30 +30,86 @@ pub enum BackgroundSize {
|
||||||
S64x64 = 3,
|
S64x64 = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MapStorage: Deref<Target = [u16]> {}
|
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||||
impl MapStorage for &[u16] {}
|
enum Mutability {
|
||||||
impl MapStorage for &mut [u16] {}
|
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
|
/// 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
|
/// automatically handles copying the correct portion of a provided map to the
|
||||||
/// assigned block depending on given coordinates.
|
/// assigned block depending on given coordinates.
|
||||||
pub struct Background<S: MapStorage> {
|
pub struct Background<'a> {
|
||||||
background: u8,
|
background: u8,
|
||||||
block: u8,
|
block: u8,
|
||||||
commited_position: Vector2D<i32>,
|
commited_position: Vector2D<i32>,
|
||||||
shadowed_position: Vector2D<i32>,
|
shadowed_position: Vector2D<i32>,
|
||||||
poisoned: bool,
|
poisoned: bool,
|
||||||
shadowed_register: u16,
|
shadowed_register: u16,
|
||||||
map: Option<Map<S>>,
|
map: Option<Map<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Map<S: MapStorage> {
|
pub struct Map<'a> {
|
||||||
pub store: S,
|
store: MapStorage<'a>,
|
||||||
pub dimensions: Vector2D<u32>,
|
pub dimensions: Vector2D<u32>,
|
||||||
pub default: u16,
|
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 {
|
fn get_position(&self, x: i32, y: i32) -> u16 {
|
||||||
if x < 0 || x as u32 >= self.dimensions.x {
|
if x < 0 || x as u32 >= self.dimensions.x {
|
||||||
self.default
|
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]
|
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> {
|
impl<'a> Background<'a> {
|
||||||
unsafe fn new(background: u8, block: u8) -> Background<S> {
|
unsafe fn new(background: u8, block: u8) -> Background<'a> {
|
||||||
let mut b = Background {
|
let mut b = Background {
|
||||||
background,
|
background,
|
||||||
block,
|
block,
|
||||||
|
@ -135,12 +197,12 @@ impl<'a, S: MapStorage> Background<S> {
|
||||||
self.shadowed_position = position;
|
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.poisoned = true;
|
||||||
self.map.as_mut()
|
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.poisoned = true;
|
||||||
self.map = Some(map);
|
self.map = Some(map);
|
||||||
}
|
}
|
||||||
|
@ -266,7 +328,7 @@ impl Tiled0 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a map background if possible and assigns an unused block to it.
|
/// 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 {
|
if self.num_backgrounds >= 4 {
|
||||||
return Err("too many backgrounds created, maximum is 4");
|
return Err("too many backgrounds created, maximum is 4");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue