dotzuki-renderer 0.1.1

A general-purpose JRPG renderer built from Game Boy tile rendering principles
Documentation
use crate::text_renderer::ScreenTileBuffer;

pub const TILE_TOP_LEFT: u8 = 0x79;
pub const TILE_TOP_RIGHT: u8 = 0x7B;
pub const TILE_BOTTOM_LEFT: u8 = 0x7D;
pub const TILE_BOTTOM_RIGHT: u8 = 0x7E;
pub const TILE_HORIZONTAL: u8 = 0x7A;
pub const TILE_VERTICAL: u8 = 0x7C;
pub const TILE_SPACE: u8 = 0x7F;
pub const TILE_DOWN_ARROW: u8 = 0xED;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TextBoxFrame {
    pub x: u32,
    pub y: u32,
    pub width: u32,
    pub height: u32,
}

impl TextBoxFrame {
    pub fn new(x: u32, y: u32, width: u32, height: u32) -> Self {
        Self {
            x,
            y,
            width,
            height,
        }
    }

    pub fn standard_dialog() -> Self {
        Self {
            x: 0,
            y: 12,
            width: 20,
            height: 6,
        }
    }

    pub fn menu_box(x: u32, y: u32, width: u32, height: u32) -> Self {
        Self {
            x,
            y,
            width,
            height,
        }
    }

    pub fn draw_frame(&self, buf: &mut ScreenTileBuffer) {
        let x = self.x;
        let y = self.y;
        let w = self.width;
        let h = self.height;

        if w < 2 || h < 2 {
            return;
        }

        let inner_w = w - 2;

        buf.set(x, y, TILE_TOP_LEFT);
        for i in 0..inner_w {
            buf.set(x + 1 + i, y, TILE_HORIZONTAL);
        }
        buf.set(x + w - 1, y, TILE_TOP_RIGHT);

        for row in 1..h - 1 {
            buf.set(x, y + row, TILE_VERTICAL);
            for col in 0..inner_w {
                buf.set(x + 1 + col, y + row, TILE_SPACE);
            }
            buf.set(x + w - 1, y + row, TILE_VERTICAL);
        }

        buf.set(x, y + h - 1, TILE_BOTTOM_LEFT);
        for i in 0..inner_w {
            buf.set(x + 1 + i, y + h - 1, TILE_HORIZONTAL);
        }
        buf.set(x + w - 1, y + h - 1, TILE_BOTTOM_RIGHT);
    }

    pub fn clear(&self, buf: &mut ScreenTileBuffer) {
        for row in 0..self.height {
            for col in 0..self.width {
                buf.set(self.x + col, self.y + row, TILE_SPACE);
            }
        }
    }

    pub fn clear_inner(&self, buf: &mut ScreenTileBuffer) {
        if self.width < 2 || self.height < 2 {
            return;
        }
        for row in 1..self.height - 1 {
            for col in 1..self.width - 1 {
                buf.set(self.x + col, self.y + row, TILE_SPACE);
            }
        }
    }

    pub fn show_down_arrow(&self, buf: &mut ScreenTileBuffer) {
        if self.width >= 2 && self.height >= 2 {
            let ax = self.x + self.width - 2;
            let ay = self.y + self.height - 2;
            buf.set(ax, ay, TILE_DOWN_ARROW);
        }
    }

    pub fn hide_down_arrow(&self, buf: &mut ScreenTileBuffer) {
        if self.width >= 2 && self.height >= 2 {
            let ax = self.x + self.width - 2;
            let ay = self.y + self.height - 2;
            buf.set(ax, ay, TILE_SPACE);
        }
    }

    pub fn text_start(&self) -> (u32, u32) {
        (self.x + 1, self.y + 2)
    }

    pub fn second_line_start(&self) -> (u32, u32) {
        (self.x + 1, self.y + 4)
    }
}