use agb::display::GraphicsFrame;
use agb::display::object::{Object, Sprite, Tag};
use agb::display::tile_data::TileData;
use agb::display::tiled::RegularBackground;
use agb::fixnum::{Vector2D, vec2};
pub trait ShowSprite {
fn show(&self, at: Vector2D<i32>, frame: &mut GraphicsFrame);
}
pub trait ShowTag {
fn show(&self, idx: usize, at: Vector2D<i32>, frame: &mut GraphicsFrame);
}
impl ShowSprite for &'static Sprite {
#[inline]
fn show(&self, at: Vector2D<i32>, frame: &mut GraphicsFrame) {
Object::new(*self).set_pos(at).show(frame);
}
}
impl ShowTag for Tag {
#[inline]
fn show(&self, idx: usize, at: Vector2D<i32>, frame: &mut GraphicsFrame) {
Object::new(self.sprite(idx)).set_pos(at).show(frame);
}
}
pub trait ShowAllTag {
fn show_all(&self, at: Vector2D<i32>, frame: &mut GraphicsFrame);
}
impl ShowAllTag for Tag {
#[inline]
fn show_all(&self, at: Vector2D<i32>, frame: &mut GraphicsFrame) {
let size = self.sprite(0).size().to_width_height();
self.sprites().iter().enumerate().for_each(|(idx, sprite)| {
let pos = at + vec2((idx * size.0) as i32, 0);
sprite.show(pos, frame);
});
}
}
#[allow(clippy::too_many_arguments)]
pub fn draw_bg_frame(
bg: &mut RegularBackground,
tile_data: &TileData,
at: Vector2D<i32>,
vert_tiles: &[u16],
horz_tiles: &[u16],
corner_tiles: &[u16],
center_tiles: &[u16],
size: (u8, u8),
) {
debug_assert!(
corner_tiles.len() == 1 || corner_tiles.len() == 4,
"corner_tiles must have 1 or 4 entries"
);
debug_assert!(
!vert_tiles.is_empty() && !horz_tiles.is_empty(),
"vert_tiles and horz_tiles must not be empty"
);
debug_assert!(size.0 >= 2 && size.1 >= 2, "frame must be at least 2x2");
let (tl, tr, bl, br) = if corner_tiles.len() == 1 {
let s = tile_data.tile_settings[corner_tiles[0] as usize];
(s, s.hflip(true), s.vflip(true), s.hflip(true).vflip(true))
} else {
(
tile_data.tile_settings[corner_tiles[0] as usize],
tile_data.tile_settings[corner_tiles[1] as usize],
tile_data.tile_settings[corner_tiles[2] as usize],
tile_data.tile_settings[corner_tiles[3] as usize],
)
};
let w = size.0 as i32;
let h = size.1 as i32;
bg.set_tile(at, &tile_data.tiles, tl);
bg.set_tile(vec2(at.x + w - 1, at.y), &tile_data.tiles, tr);
bg.set_tile(vec2(at.x, at.y + h - 1), &tile_data.tiles, bl);
bg.set_tile(vec2(at.x + w - 1, at.y + h - 1), &tile_data.tiles, br);
for (i, &tile_idx) in (1..w - 1).zip(vert_tiles.iter().cycle()) {
let s = tile_data.tile_settings[tile_idx as usize];
bg.set_tile(vec2(at.x + i, at.y), &tile_data.tiles, s);
bg.set_tile(
vec2(at.x + i, at.y + h - 1),
&tile_data.tiles,
s.vflip(true),
);
}
for (i, &tile_idx) in (1..h - 1).zip(horz_tiles.iter().cycle()) {
let s = tile_data.tile_settings[tile_idx as usize];
bg.set_tile(vec2(at.x, at.y + i), &tile_data.tiles, s);
bg.set_tile(
vec2(at.x + w - 1, at.y + i),
&tile_data.tiles,
s.hflip(true),
);
}
if !center_tiles.is_empty() {
for i in 1..h - 1 {
for (j, &c_idx) in (1..w - 1).zip(center_tiles.iter().cycle()) {
bg.set_tile(
vec2(at.x + j, at.y + i),
&tile_data.tiles,
tile_data.tile_settings[c_idx as usize],
);
}
}
}
}
pub fn draw_bg_tiles(
bg: &mut RegularBackground,
tile_data: &TileData,
pos: Vector2D<i32>,
start_tile_idx: u16,
bg_image_width_tiles: u16,
meta_tile_size: (u16, u16),
count: (u8, u8),
) {
let count = (count.0 as i32, count.1 as i32);
let meta_tile_size = (meta_tile_size.0 as i32, meta_tile_size.1 as i32);
let start_tile_idx = start_tile_idx as i32;
let bg_image_width_tiles = bg_image_width_tiles as i32;
for meta_row in 0..meta_tile_size.1 {
for meta_col in 0..meta_tile_size.0 {
let tile_idx = start_tile_idx + meta_row * bg_image_width_tiles + meta_col;
let setting = tile_data.tile_settings[tile_idx as usize];
for vr in 0..count.1 {
for hr in 0..count.0 {
bg.set_tile(
vec2(
pos.x + hr * meta_tile_size.0 + meta_col,
pos.y + vr * meta_tile_size.1 + meta_row,
),
&tile_data.tiles,
setting,
);
}
}
}
}
}