use crate::background::Background;
use crate::rgb::Rgb;
use crate::sprite::Sprite;
use crate::{
Buttons, BACKGROUND_MAX_SIZE, DPAD_DOWN, DPAD_LEFT, DPAD_RIGHT, DPAD_UP, EMPTY_TILE,
MAX_BACKGROUNDS, MAX_SPRITES,
};
use ascii::{AsciiChar, AsciiStr};
use glam::IVec2;
pub struct Gsa {
pub sprites: [Sprite; MAX_SPRITES],
pub palette: [Rgb; 256],
pub bgs: [Background; MAX_BACKGROUNDS],
pub font: u16,
pub(crate) pressed: Buttons,
pub(crate) released: Buttons,
pub(crate) down: Buttons,
}
impl Gsa {
pub fn clear_bg(&mut self, bg: usize) {
self.fill_bg(bg, EMPTY_TILE);
}
pub fn reset_bgs(&mut self) {
for bg in 0..MAX_BACKGROUNDS {
self.clear_bg(bg);
self.bgs[bg].scroll = IVec2::ZERO;
self.bgs[bg].half_tile = false;
}
self.bgs[3].half_tile = true;
}
pub fn reset_sprites(&mut self) {
for sprite in 0..MAX_SPRITES {
self.sprites[sprite].pos = IVec2::ZERO;
self.sprites[sprite].tile = EMPTY_TILE;
self.sprites[sprite].priority = 0;
}
}
pub fn fill_bg(&mut self, bg: usize, val: u16) {
for x in 0..BACKGROUND_MAX_SIZE {
for y in 0..BACKGROUND_MAX_SIZE {
self.bgs[bg].tiles[x][y] = val;
}
}
}
pub fn button_down(&self, button: Buttons) -> bool {
self.down & button != 0
}
pub fn button_pressed(&self, button: Buttons) -> bool {
self.pressed & button != 0
}
pub fn button_released(&self, button: Buttons) -> bool {
self.released & button != 0
}
pub fn input_dir(&self) -> IVec2 {
IVec2 {
x: if self.button_down(DPAD_LEFT) { -1 } else { 0 }
+ if self.button_down(DPAD_RIGHT) { 1 } else { 0 },
y: if self.button_down(DPAD_UP) { -1 } else { 0 }
+ if self.button_down(DPAD_DOWN) { 1 } else { 0 },
}
}
pub fn write_string(&mut self, map: usize, pos: IVec2, str: &str) {
let str = AsciiStr::from_ascii(str).unwrap();
for (i, ch) in str.into_iter().enumerate() {
self.bgs[map].tiles[pos.x as usize + i][pos.y as usize] = self.get_char_tile(*ch);
}
}
fn get_char_tile(&self, ch: AsciiChar) -> u16 {
let ch = ch as u16;
self.font + (ch % 0x10) + (ch / 0x10) * 0x100
}
}