dotzuki_renderer/
window_layer.rs1use crate::palette::Palette;
12use crate::tile::TileSet;
13use crate::tilemap::BG_MAP_PIXEL_HEIGHT;
14use crate::tilemap::BG_MAP_PIXEL_WIDTH;
15use dotzuki_engine::tilemap::Tilemap;
16use crate::{FbSurface, TILE_SIZE};
17
18#[derive(Debug, Clone)]
20pub struct WindowLayer {
21 pub tilemap: Tilemap,
23 pub wx: u32,
26 pub wy: u32,
29 pub enabled: bool,
31}
32
33impl WindowLayer {
34 pub fn new() -> Self {
35 Self {
36 tilemap: Tilemap::new(32, 32),
37 wx: 7, wy: 0, enabled: false,
40 }
41 }
42
43 #[inline]
46 pub fn screen_x(&self) -> u32 {
47 if self.wx < 7 {
48 0
49 } else {
50 self.wx - 7
51 }
52 }
53
54 pub fn render(&self, fb: &mut impl FbSurface, tileset: &TileSet, palette: &Palette) {
58 if !self.enabled {
59 return;
60 }
61
62 let win_start_x = self.screen_x();
63 if win_start_x >= fb.width() || self.wy >= fb.height() {
64 return;
65 }
66
67 for screen_y in self.wy..fb.height() {
68 self.render_scanline(fb, tileset, palette, screen_y);
69 }
70 }
71
72 pub fn render_scanline(
74 &self,
75 fb: &mut impl FbSurface,
76 tileset: &TileSet,
77 palette: &Palette,
78 screen_y: u32,
79 ) {
80 if !self.enabled || screen_y < self.wy {
81 return;
82 }
83
84 let win_start_x = self.screen_x();
85 if win_start_x >= fb.width() {
86 return;
87 }
88
89 let win_y = screen_y - self.wy;
91 if win_y >= BG_MAP_PIXEL_HEIGHT {
92 return;
93 }
94
95 let tile_row = win_y / TILE_SIZE;
96 let pixel_row = (win_y % TILE_SIZE) as usize;
97
98 for screen_x in win_start_x..fb.width() {
99 let win_x = screen_x - win_start_x;
100 if win_x >= BG_MAP_PIXEL_WIDTH {
101 break;
102 }
103
104 let tile_col = win_x / TILE_SIZE;
105 let pixel_col = (win_x % TILE_SIZE) as usize;
106
107 let tile_index = self
108 .tilemap
109 .get(tile_col as u16, tile_row as u16)
110 .map(|e| e.tile_id as usize)
111 .unwrap_or(0);
112 let tile = tileset.get(tile_index);
113 let color_idx = tile.get(pixel_row, pixel_col);
114
115 let rgba = palette.color(crate::palette::GbColor::from_u8(color_idx));
116 fb.set_pixel(screen_x, screen_y, rgba);
117 }
118 }
119}
120
121impl Default for WindowLayer {
122 fn default() -> Self {
123 Self::new()
124 }
125}