feat: store color directly in Cell (reality layer)
Each cell now stores its own fg/bg color inline, instead of looking up from MaterialRegistry every frame. Cell struct: - fg: [u8; 3] — foreground color (for rendering) - bg: [u8; 3] — background color (for rendering) - temp: f32 — temperature (already there) - material: MaterialId — for physics property lookup - variant: u8 — visual/behavioral variant - updated_this_tick: bool — CA flag Colors are copied from MaterialRegistry at Cell::new() time. This allows per-cell color variation in the future (water depth shading, lava gradient, damaged materials, etc.) without registry changes. MaterialRegistry still stores physics properties (density, solid, liquid, flammable, etc.) — looked up only during CA/physics steps, not during rendering. Renderers (terminal, ascii, graphics) updated to use cell.fg/cell.bg directly — no more registry lookup in render path. Cell size: ~16 bytes (was ~12). 250x250 grid = 1MB (was 750KB). 126 tests, 0 failures
This commit is contained in:
@@ -344,7 +344,6 @@ impl GraphicsRenderer {
|
|||||||
[40, 40, 40, 255]
|
[40, 40, 40, 255]
|
||||||
} else {
|
} else {
|
||||||
let cell = grid.get(wx, wy);
|
let cell = grid.get(wx, wy);
|
||||||
let mat = reg.get(cell.material);
|
|
||||||
if cell.is_empty() {
|
if cell.is_empty() {
|
||||||
bg_default
|
bg_default
|
||||||
} else {
|
} else {
|
||||||
@@ -352,7 +351,7 @@ impl GraphicsRenderer {
|
|||||||
let r = 200u8.saturating_add(cell.variant / 2);
|
let r = 200u8.saturating_add(cell.variant / 2);
|
||||||
[r, 60, 20, 255]
|
[r, 60, 20, 255]
|
||||||
} else {
|
} else {
|
||||||
[mat.color_fg.0, mat.color_fg.1, mat.color_fg.2, 255]
|
[cell.fg[0], cell.fg[1], cell.fg[2], 255]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+5
-13
@@ -86,26 +86,18 @@ impl Renderer for TerminalRenderer {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let cell = grid.get(wx, wy);
|
let cell = grid.get(wx, wy);
|
||||||
let mat = reg.get(cell.material);
|
|
||||||
let idx = dy * self.width + dx;
|
let idx = dy * self.width + dx;
|
||||||
if cell.is_empty() {
|
if cell.is_empty() {
|
||||||
frame[idx] = (' ', mat.color_fg, mat.color_bg);
|
frame[idx] = (' ', (cell.fg[0], cell.fg[1], cell.fg[2]), (cell.bg[0], cell.bg[1], cell.bg[2]));
|
||||||
} else {
|
} else {
|
||||||
let ch = if cell.material == MaterialId::Lava {
|
let ch = cell.material.display_char();
|
||||||
if cell.variant % 2 == 0 { '#' } else { '#' }
|
|
||||||
} else if cell.material == MaterialId::Water {
|
|
||||||
if cell.variant % 3 == 0 { '~' } else { '~' }
|
|
||||||
} else {
|
|
||||||
mat.display_char
|
|
||||||
};
|
|
||||||
let fg = if cell.material == MaterialId::Lava {
|
let fg = if cell.material == MaterialId::Lava {
|
||||||
let flicker = cell.variant;
|
let r = 200u8.saturating_add(cell.variant / 2);
|
||||||
let r = 200u8.saturating_add(flicker / 2);
|
|
||||||
(r, 60, 20)
|
(r, 60, 20)
|
||||||
} else {
|
} else {
|
||||||
mat.color_fg
|
(cell.fg[0], cell.fg[1], cell.fg[2])
|
||||||
};
|
};
|
||||||
frame[idx] = (ch, fg, mat.color_bg);
|
frame[idx] = (ch, fg, (cell.bg[0], cell.bg[1], cell.bg[2]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,7 +207,6 @@ impl VulkanRenderer {
|
|||||||
('?', [80, 80, 80, 255], bg_default)
|
('?', [80, 80, 80, 255], bg_default)
|
||||||
} else {
|
} else {
|
||||||
let cell = grid.get(wx, wy);
|
let cell = grid.get(wx, wy);
|
||||||
let mat = reg.get(cell.material);
|
|
||||||
if cell.is_empty() {
|
if cell.is_empty() {
|
||||||
(' ', [10, 10, 15, 255], bg_default)
|
(' ', [10, 10, 15, 255], bg_default)
|
||||||
} else {
|
} else {
|
||||||
@@ -215,10 +214,10 @@ impl VulkanRenderer {
|
|||||||
let r = 200u8.saturating_add(cell.variant / 2);
|
let r = 200u8.saturating_add(cell.variant / 2);
|
||||||
[r, 60, 20, 255]
|
[r, 60, 20, 255]
|
||||||
} else {
|
} else {
|
||||||
[mat.color_fg.0, mat.color_fg.1, mat.color_fg.2, 255]
|
[cell.fg[0], cell.fg[1], cell.fg[2], 255]
|
||||||
};
|
};
|
||||||
let bg = [mat.color_bg.0, mat.color_bg.1, mat.color_bg.2, 255];
|
let bg = [cell.bg[0], cell.bg[1], cell.bg[2], 255];
|
||||||
(mat.display_char, fg, bg)
|
(cell.material.display_char(), fg, bg)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ pub struct Cell {
|
|||||||
pub temp: f32,
|
pub temp: f32,
|
||||||
pub updated_this_tick: bool,
|
pub updated_this_tick: bool,
|
||||||
pub variant: u8,
|
pub variant: u8,
|
||||||
|
pub fg: [u8; 3],
|
||||||
|
pub bg: [u8; 3],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cell {
|
impl Cell {
|
||||||
@@ -76,10 +78,14 @@ impl Cell {
|
|||||||
temp: 20.0,
|
temp: 20.0,
|
||||||
updated_this_tick: false,
|
updated_this_tick: false,
|
||||||
variant: 0,
|
variant: 0,
|
||||||
|
fg: [15, 15, 20],
|
||||||
|
bg: [10, 10, 15],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(material: MaterialId) -> Self {
|
pub fn new(material: MaterialId) -> Self {
|
||||||
|
let reg = MaterialRegistry::instance();
|
||||||
|
let mat = reg.get(material);
|
||||||
let temp = match material {
|
let temp = match material {
|
||||||
MaterialId::Lava => 1500.0,
|
MaterialId::Lava => 1500.0,
|
||||||
MaterialId::Fire => 800.0,
|
MaterialId::Fire => 800.0,
|
||||||
@@ -92,6 +98,8 @@ impl Cell {
|
|||||||
temp,
|
temp,
|
||||||
updated_this_tick: false,
|
updated_this_tick: false,
|
||||||
variant: rand_u8(),
|
variant: rand_u8(),
|
||||||
|
fg: [mat.color_fg.0, mat.color_fg.1, mat.color_fg.2],
|
||||||
|
bg: [mat.color_bg.0, mat.color_bg.1, mat.color_bg.2],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user