From d889e24cf626b16653140bd95765d560bf84569d Mon Sep 17 00:00:00 2001 From: Emil Date: Sun, 21 Jun 2026 01:21:38 +0300 Subject: [PATCH] feat: store color directly in Cell (reality layer) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/render/graphics.rs | 3 +-- src/render/terminal.rs | 18 +++++------------- src/render/vulkan.rs | 7 +++---- src/world/cell.rs | 8 ++++++++ 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/render/graphics.rs b/src/render/graphics.rs index 470138a..3aaab26 100644 --- a/src/render/graphics.rs +++ b/src/render/graphics.rs @@ -344,7 +344,6 @@ impl GraphicsRenderer { [40, 40, 40, 255] } else { let cell = grid.get(wx, wy); - let mat = reg.get(cell.material); if cell.is_empty() { bg_default } else { @@ -352,7 +351,7 @@ impl GraphicsRenderer { let r = 200u8.saturating_add(cell.variant / 2); [r, 60, 20, 255] } else { - [mat.color_fg.0, mat.color_fg.1, mat.color_fg.2, 255] + [cell.fg[0], cell.fg[1], cell.fg[2], 255] } } }; diff --git a/src/render/terminal.rs b/src/render/terminal.rs index 5141ffc..80eb75b 100644 --- a/src/render/terminal.rs +++ b/src/render/terminal.rs @@ -86,26 +86,18 @@ impl Renderer for TerminalRenderer { continue; } let cell = grid.get(wx, wy); - let mat = reg.get(cell.material); let idx = dy * self.width + dx; 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 { - let ch = if cell.material == MaterialId::Lava { - if cell.variant % 2 == 0 { '#' } else { '#' } - } else if cell.material == MaterialId::Water { - if cell.variant % 3 == 0 { '~' } else { '~' } - } else { - mat.display_char - }; + let ch = cell.material.display_char(); let fg = if cell.material == MaterialId::Lava { - let flicker = cell.variant; - let r = 200u8.saturating_add(flicker / 2); + let r = 200u8.saturating_add(cell.variant / 2); (r, 60, 20) } 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])); } } } diff --git a/src/render/vulkan.rs b/src/render/vulkan.rs index 2f46243..56f9c4d 100644 --- a/src/render/vulkan.rs +++ b/src/render/vulkan.rs @@ -207,7 +207,6 @@ impl VulkanRenderer { ('?', [80, 80, 80, 255], bg_default) } else { let cell = grid.get(wx, wy); - let mat = reg.get(cell.material); if cell.is_empty() { (' ', [10, 10, 15, 255], bg_default) } else { @@ -215,10 +214,10 @@ impl VulkanRenderer { let r = 200u8.saturating_add(cell.variant / 2); [r, 60, 20, 255] } 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]; - (mat.display_char, fg, bg) + let bg = [cell.bg[0], cell.bg[1], cell.bg[2], 255]; + (cell.material.display_char(), fg, bg) } }; diff --git a/src/world/cell.rs b/src/world/cell.rs index 6812e5a..1ef6aee 100644 --- a/src/world/cell.rs +++ b/src/world/cell.rs @@ -67,6 +67,8 @@ pub struct Cell { pub temp: f32, pub updated_this_tick: bool, pub variant: u8, + pub fg: [u8; 3], + pub bg: [u8; 3], } impl Cell { @@ -76,10 +78,14 @@ impl Cell { temp: 20.0, updated_this_tick: false, variant: 0, + fg: [15, 15, 20], + bg: [10, 10, 15], } } pub fn new(material: MaterialId) -> Self { + let reg = MaterialRegistry::instance(); + let mat = reg.get(material); let temp = match material { MaterialId::Lava => 1500.0, MaterialId::Fire => 800.0, @@ -92,6 +98,8 @@ impl Cell { temp, updated_this_tick: false, 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], } }