mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 16:21:33 +11:00
make dynamic sprite better
This commit is contained in:
parent
e8479c093b
commit
f95d68187b
|
@ -368,4 +368,11 @@ impl Size {
|
||||||
Size::S32x64 => (32, 64),
|
Size::S32x64 => (32, 64),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
/// Returns the width and height of the size in pixels.
|
||||||
|
pub const fn to_tiles_width_height(self) -> (usize, usize) {
|
||||||
|
let wh = self.to_width_height();
|
||||||
|
(wh.0 / 8, wh.1 / 8)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
use core::ptr::NonNull;
|
use core::{alloc::Allocator, ptr::NonNull};
|
||||||
|
|
||||||
use alloc::rc::{Rc, Weak};
|
use alloc::{
|
||||||
|
alloc::Global,
|
||||||
|
boxed::Box,
|
||||||
|
rc::{Rc, Weak},
|
||||||
|
vec::Vec,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
agb_alloc::{block_allocator::BlockAllocator, bump_allocator::StartEnd},
|
agb_alloc::{block_allocator::BlockAllocator, bump_allocator::StartEnd},
|
||||||
|
@ -285,34 +290,61 @@ impl Default for SpriteLoader {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sprite data that can be used to create sprites in vram.
|
/// Sprite data that can be used to create sprites in vram.
|
||||||
pub struct DynamicSprite<'a> {
|
pub struct DynamicSprite<A: Allocator = Global> {
|
||||||
data: &'a [u8],
|
data: Box<[u8], A>,
|
||||||
size: Size,
|
size: Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DynamicSprite<'_> {
|
impl DynamicSprite {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
/// Creates a new dynamic sprite from underlying bytes. Note that despite
|
/// Creates a new dynamic sprite.
|
||||||
/// being an array of u8, this must be aligned to at least a 2 byte
|
pub fn new(size: Size) -> Self {
|
||||||
/// boundary.
|
Self::new_in(size, Global)
|
||||||
pub fn new(data: &[u8], size: Size) -> DynamicSprite {
|
}
|
||||||
let ptr = &data[0] as *const _ as usize;
|
}
|
||||||
if ptr % 2 != 0 {
|
|
||||||
panic!("data is not aligned to a 2 byte boundary");
|
impl<A: Allocator> DynamicSprite<A> {
|
||||||
}
|
#[must_use]
|
||||||
if data.len() != size.number_of_tiles() * BYTES_PER_TILE_4BPP {
|
/// Creates a new dynamic sprite of a given size in a given allocator.
|
||||||
panic!(
|
pub fn new_in(size: Size, allocator: A) -> Self {
|
||||||
"data is not of expected length, got {} expected {}",
|
let num_bytes = size.number_of_tiles() * BYTES_PER_TILE_4BPP;
|
||||||
data.len(),
|
let mut data = Vec::with_capacity_in(num_bytes, allocator);
|
||||||
size.number_of_tiles() * BYTES_PER_TILE_4BPP
|
|
||||||
);
|
data.resize(num_bytes, 0);
|
||||||
}
|
|
||||||
|
let data = data.into_boxed_slice();
|
||||||
|
|
||||||
DynamicSprite { data, size }
|
DynamicSprite { data, size }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the pixel of a sprite to a given paletted pixel. Panics if the
|
||||||
|
/// coordinate is out of range of the sprite or if the paletted pixel is
|
||||||
|
/// greater than 4 bits.
|
||||||
|
pub fn set_pixel(&mut self, x: usize, y: usize, paletted_pixel: usize) {
|
||||||
|
assert!(paletted_pixel < 0x10);
|
||||||
|
|
||||||
|
let (sprite_pixel_x, sprite_pixel_y) = self.size.to_width_height();
|
||||||
|
assert!(x < sprite_pixel_x, "x too big for sprite size");
|
||||||
|
assert!(y < sprite_pixel_y, "y too big for sprite size");
|
||||||
|
|
||||||
|
let (sprite_tile_x, _) = self.size.to_tiles_width_height();
|
||||||
|
|
||||||
|
let (adjust_tile_x, adjust_tile_y) = (x / 8, y / 8);
|
||||||
|
|
||||||
|
let tile_number_to_modify = adjust_tile_x + adjust_tile_y * sprite_tile_x;
|
||||||
|
|
||||||
|
let byte_to_modify_in_tile = x / 2 + y * 4;
|
||||||
|
let byte_to_modify = tile_number_to_modify * BYTES_PER_TILE_4BPP + byte_to_modify_in_tile;
|
||||||
|
let mut byte = self.data[byte_to_modify];
|
||||||
|
let parity = (x & 0b1) * 4;
|
||||||
|
|
||||||
|
byte = (byte & !(0b1111 << parity)) | ((paletted_pixel as u8) << parity);
|
||||||
|
self.data[byte_to_modify] = byte;
|
||||||
|
}
|
||||||
|
|
||||||
/// Tries to copy the sprite to vram to be used to set object sprites.
|
/// Tries to copy the sprite to vram to be used to set object sprites.
|
||||||
pub fn try_vram(&self, palette: PaletteVram) -> Result<SpriteVram, LoaderError> {
|
pub fn try_vram(&self, palette: PaletteVram) -> Result<SpriteVram, LoaderError> {
|
||||||
SpriteVram::new(self.data, self.size, palette)
|
SpriteVram::new(&self.data, self.size, palette)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
|
Loading…
Reference in a new issue