use crate::rgb::Rgb; use crate::sprite::Sprite; use crate::tilemap::Tilemap; use crate::{ Buttons, DPAD_DOWN, DPAD_LEFT, DPAD_RIGHT, DPAD_UP, MAX_SPRITES, MAX_TILEMAPS, TILEMAP_MAX_SIZE, }; use ascii::{AsciiChar, AsciiStr}; use glam::IVec2; /// Complete state of GSA pub struct Gsa { /// Sprites available pub sprites: [Sprite; MAX_SPRITES], /// Palette used to draw graphics, initially loaded from gfx.gif pub palette: [Rgb; 256], /// Tilemap layers available pub maps: [Tilemap; MAX_TILEMAPS], /// Currently selected font /// /// Chosen as half-size tile index, extends 16x16 half tiles in x and y pub font: u16, pub(crate) pressed: Buttons, pub(crate) released: Buttons, pub(crate) down: Buttons, } impl Gsa { /// Clears all tiles of given map to 0 pub fn clear_map(&mut self, map: usize) { self.fill_map(map, 0); } /// Sets all tiles of map to val pub fn fill_map(&mut self, map: usize, val: u16) { for x in 0..TILEMAP_MAX_SIZE { for y in 0..TILEMAP_MAX_SIZE { self.maps[map].tiles[x][y] = val; } } } /// Checks if any of given buttons currently held down pub fn button_down(&self, button: Buttons) -> bool { self.down & button != 0 } /// Checks if any of given buttons been pressed in the current frame pub fn button_pressed(&self, button: Buttons) -> bool { self.pressed & button != 0 } /// Checks if any of given buttons been released in the current frame pub fn button_released(&self, button: Buttons) -> bool { self.released & button != 0 } /// Directional vector (-1 to 1) from current dpad state 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 }, } } /// Write given string on given map, at given position, with font [Gsa::font] 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.maps[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 } }