From ab23631e66b224976274262b850f2cfa9b102c69 Mon Sep 17 00:00:00 2001 From: Matthew Rothlisberger Date: Wed, 18 Jun 2025 09:59:20 -0400 Subject: [PATCH 1/4] reimplements PSX Doom fire animation; adds flame height control --- res/config.ini | 13 +++++++-- src/animations/Doom.zig | 64 ++++++++++++++++++++++++++++++----------- src/config/Config.zig | 2 ++ src/main.zig | 2 +- 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/res/config.ini b/res/config.ini index 526c6f9..cabc070 100644 --- a/res/config.ini +++ b/res/config.ini @@ -104,13 +104,20 @@ colormix_col3 = 0x20000000 # Available inputs: info_line, session, login, password default_input = login -# DOOM animation top color (low intensity flames) +# DOOM animation fire height (1 thru 9) +doom_fire_height = 6 + +# DOOM animation use natural fire colors +# If false, below custom colors used +doom_default_colors = true + +# DOOM animation custom top color (low intensity flames) doom_top_color = 0x00FF0000 -# DOOM animation middle color (medium intensity flames) +# DOOM animation custom middle color (medium intensity flames) doom_middle_color = 0x00FFFF00 -# DOOM animation bottom color (high intensity flames) +# DOOM animation custom bottom color (high intensity flames) doom_bottom_color = 0x00FFFFFF # Error background color id diff --git a/src/animations/Doom.zig b/src/animations/Doom.zig index 41de5ee..fe90ad4 100644 --- a/src/animations/Doom.zig +++ b/src/animations/Doom.zig @@ -11,17 +11,31 @@ pub const STEPS = 12; allocator: Allocator, terminal_buffer: *TerminalBuffer, buffer: []u8, +height: u8, fire: [STEPS + 1]Cell, -pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, top_color: u32, middle_color: u32, bottom_color: u32) !Doom { +pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, fire_height: u8, default_colors: bool, top_color: u32, middle_color: u32, bottom_color: u32) !Doom { const buffer = try allocator.alloc(u8, terminal_buffer.width * terminal_buffer.height); initBuffer(buffer, terminal_buffer.width); - return .{ - .allocator = allocator, - .terminal_buffer = terminal_buffer, - .buffer = buffer, - .fire = [_]Cell{ + const levels = if (default_colors) + [_]Cell{ + Cell.init(' ', TerminalBuffer.Color.DEFAULT, TerminalBuffer.Color.DEFAULT), + Cell.init(0x2591, 0x070707, TerminalBuffer.Color.DEFAULT), + Cell.init(0x2592, 0x470F07, TerminalBuffer.Color.DEFAULT), + Cell.init(0x2593, 0x771F07, TerminalBuffer.Color.DEFAULT), + Cell.init(0x2588, 0xAF3F07, TerminalBuffer.Color.DEFAULT), + Cell.init(0x2591, 0xC74707, 0xAF3F07), + Cell.init(0x2592, 0xDF5707, 0xAF3F07), + Cell.init(0x2593, 0xCF6F0F, 0xAF3F07), + Cell.init(0x2588, 0xC78F17, 0xAF3F07), + Cell.init(0x2591, 0xBF9F1F, 0xAF3F07), + Cell.init(0x2592, 0xBFAF2F, 0xAF3F07), + Cell.init(0x2593, 0xCFCF6F, 0xAF3F07), + Cell.init(0x2588, 0xFFFFFF, 0xAF3F07), + } + else + [_]Cell{ Cell.init(' ', TerminalBuffer.Color.DEFAULT, TerminalBuffer.Color.DEFAULT), Cell.init(0x2591, top_color, TerminalBuffer.Color.DEFAULT), Cell.init(0x2592, top_color, TerminalBuffer.Color.DEFAULT), @@ -35,7 +49,14 @@ pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, top_color: u Cell.init(0x2592, bottom_color, middle_color), Cell.init(0x2593, bottom_color, middle_color), Cell.init(0x2588, bottom_color, middle_color), - }, + }; + + return .{ + .allocator = allocator, + .terminal_buffer = terminal_buffer, + .buffer = buffer, + .height = @min(9, fire_height), + .fire = levels, }; } @@ -57,20 +78,31 @@ fn draw(self: *Doom) void { for (0..self.terminal_buffer.width) |x| { // We start from 1 so that we always have the topmost line when spreading fire for (1..self.terminal_buffer.height) |y| { - // Get current cell + // Get index of current cell in fire level buffer const from = y * self.terminal_buffer.width + x; - const cell_index = self.buffer[from]; - // Spread fire - const propagate = self.terminal_buffer.random.int(u1); - const to = from - self.terminal_buffer.width; // Get the line above + // Generate random datum for fire propagation + const random = (self.terminal_buffer.random.int(u16) % 10); - self.buffer[to] = if (cell_index > 0) cell_index - propagate else cell_index; + // Select semi-random target cell + const to = from -| self.terminal_buffer.width -| (random & 3) + 1; - // Put the cell - const cell = self.fire[cell_index]; - cell.put(x, y); + // Get fire level of current cell + const level_buf_from = self.buffer[from]; + + // Choose new fire level and store in level buffer + var level_buf_to = level_buf_from; + if (random >= self.height) level_buf_to -|= 1; + self.buffer[to] = @intCast(level_buf_to); + + // Send fire level to terminal buffer + const to_cell = self.fire[level_buf_to]; + to_cell.put(x, y); } + + // Draw bottom line (fire source) + const src_cell = self.fire[STEPS]; + src_cell.put(x, self.terminal_buffer.height - 1); } } diff --git a/src/config/Config.zig b/src/config/Config.zig index 874a75e..613c55a 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -29,6 +29,8 @@ colormix_col1: u32 = 0x00FF0000, colormix_col2: u32 = 0x000000FF, colormix_col3: u32 = 0x20000000, default_input: Input = .login, +doom_fire_height: u8 = 6, +doom_default_colors: bool = true, doom_top_color: u32 = 0x00FF0000, doom_middle_color: u32 = 0x00FFFF00, doom_bottom_color: u32 = 0x00FFFFFF, diff --git a/src/main.zig b/src/main.zig index 9e51691..b14a462 100644 --- a/src/main.zig +++ b/src/main.zig @@ -354,7 +354,7 @@ pub fn main() !void { animation = dummy.animation(); }, .doom => { - var doom = try Doom.init(allocator, &buffer, config.doom_top_color, config.doom_middle_color, config.doom_bottom_color); + var doom = try Doom.init(allocator, &buffer, config.doom_fire_height, config.doom_default_colors, config.doom_top_color, config.doom_middle_color, config.doom_bottom_color); animation = doom.animation(); }, .matrix => { From 1c5686ea545fa19ca58a57f672ddcd91eee7ecb3 Mon Sep 17 00:00:00 2001 From: Matthew Rothlisberger Date: Fri, 20 Jun 2025 10:23:17 -0400 Subject: [PATCH 2/4] further improves fire behavior --- src/animations/Doom.zig | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/animations/Doom.zig b/src/animations/Doom.zig index fe90ad4..f988495 100644 --- a/src/animations/Doom.zig +++ b/src/animations/Doom.zig @@ -24,14 +24,14 @@ pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, fire_height: Cell.init(0x2591, 0x070707, TerminalBuffer.Color.DEFAULT), Cell.init(0x2592, 0x470F07, TerminalBuffer.Color.DEFAULT), Cell.init(0x2593, 0x771F07, TerminalBuffer.Color.DEFAULT), - Cell.init(0x2588, 0xAF3F07, TerminalBuffer.Color.DEFAULT), - Cell.init(0x2591, 0xC74707, 0xAF3F07), - Cell.init(0x2592, 0xDF5707, 0xAF3F07), - Cell.init(0x2593, 0xCF6F0F, 0xAF3F07), - Cell.init(0x2588, 0xC78F17, 0xAF3F07), - Cell.init(0x2591, 0xBF9F1F, 0xAF3F07), - Cell.init(0x2592, 0xBFAF2F, 0xAF3F07), - Cell.init(0x2593, 0xCFCF6F, 0xAF3F07), + Cell.init(0x2588, 0x9F2F07, TerminalBuffer.Color.DEFAULT), + Cell.init(0x2591, 0xBF4707, 0xAF3F07), + Cell.init(0x2592, 0xC74707, 0xAF3F07), + Cell.init(0x2593, 0xDF5707, 0xAF3F07), + Cell.init(0x2588, 0xCF6F0F, 0xAF3F07), + Cell.init(0x2591, 0xC78F17, 0xAF3F07), + Cell.init(0x2592, 0xBF9F1F, 0xAF3F07), + Cell.init(0x2593, 0xBFAF2F, 0xAF3F07), Cell.init(0x2588, 0xFFFFFF, 0xAF3F07), } else @@ -82,10 +82,12 @@ fn draw(self: *Doom) void { const from = y * self.terminal_buffer.width + x; // Generate random datum for fire propagation - const random = (self.terminal_buffer.random.int(u16) % 10); + const random = (self.terminal_buffer.random.int(u8) % 10); // Select semi-random target cell const to = from -| self.terminal_buffer.width -| (random & 3) + 1; + const to_x = to % self.terminal_buffer.width; + const to_y = to / self.terminal_buffer.width; // Get fire level of current cell const level_buf_from = self.buffer[from]; @@ -95,9 +97,11 @@ fn draw(self: *Doom) void { if (random >= self.height) level_buf_to -|= 1; self.buffer[to] = @intCast(level_buf_to); - // Send fire level to terminal buffer + // Send known fire levels to terminal buffer + const from_cell = self.fire[level_buf_from]; const to_cell = self.fire[level_buf_to]; - to_cell.put(x, y); + from_cell.put(x, y); + to_cell.put(to_x, to_y); } // Draw bottom line (fire source) From 2a8e221e80240c690c7cdbf9b35cf4ca3736e5d7 Mon Sep 17 00:00:00 2001 From: Matthew Rothlisberger Date: Fri, 20 Jun 2025 22:22:29 -0400 Subject: [PATCH 3/4] improves fire gradient in true color mode --- src/animations/Doom.zig | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/animations/Doom.zig b/src/animations/Doom.zig index f988495..721eead 100644 --- a/src/animations/Doom.zig +++ b/src/animations/Doom.zig @@ -21,18 +21,18 @@ pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, fire_height: const levels = if (default_colors) [_]Cell{ Cell.init(' ', TerminalBuffer.Color.DEFAULT, TerminalBuffer.Color.DEFAULT), - Cell.init(0x2591, 0x070707, TerminalBuffer.Color.DEFAULT), - Cell.init(0x2592, 0x470F07, TerminalBuffer.Color.DEFAULT), - Cell.init(0x2593, 0x771F07, TerminalBuffer.Color.DEFAULT), - Cell.init(0x2588, 0x9F2F07, TerminalBuffer.Color.DEFAULT), - Cell.init(0x2591, 0xBF4707, 0xAF3F07), - Cell.init(0x2592, 0xC74707, 0xAF3F07), - Cell.init(0x2593, 0xDF5707, 0xAF3F07), - Cell.init(0x2588, 0xCF6F0F, 0xAF3F07), - Cell.init(0x2591, 0xC78F17, 0xAF3F07), - Cell.init(0x2592, 0xBF9F1F, 0xAF3F07), - Cell.init(0x2593, 0xBFAF2F, 0xAF3F07), - Cell.init(0x2588, 0xFFFFFF, 0xAF3F07), + Cell.init(0x2591, 0x009F2707, TerminalBuffer.Color.DEFAULT), + Cell.init(0x2592, 0x009F2707, TerminalBuffer.Color.DEFAULT), + Cell.init(0x2593, 0x009F2707, TerminalBuffer.Color.DEFAULT), + Cell.init(0x2588, 0x009F2707, TerminalBuffer.Color.DEFAULT), + Cell.init(0x2591, 0x00C78F17, 0x009F2707), + Cell.init(0x2592, 0x00C78F17, 0x009F2707), + Cell.init(0x2593, 0x00C78F17, 0x009F2707), + Cell.init(0x2588, 0x00C78F17, 0x009F2707), + Cell.init(0x2591, 0x00FFFFFF, 0x00C78F17), + Cell.init(0x2592, 0x00FFFFFF, 0x00C78F17), + Cell.init(0x2593, 0x00FFFFFF, 0x00C78F17), + Cell.init(0x2588, 0x00FFFFFF, 0x00C78F17), } else [_]Cell{ From 99f3ab96ba04554d300ba5db90d276e2913a3d81 Mon Sep 17 00:00:00 2001 From: Matthew Rothlisberger Date: Mon, 7 Jul 2025 21:01:36 -0400 Subject: [PATCH 4/4] changes fire parameters --- res/config.ini | 9 ++++----- src/animations/Doom.zig | 38 +++++++++++++------------------------- src/config/Config.zig | 2 +- src/main.zig | 2 +- 4 files changed, 19 insertions(+), 32 deletions(-) diff --git a/res/config.ini b/res/config.ini index cabc070..492319c 100644 --- a/res/config.ini +++ b/res/config.ini @@ -107,15 +107,14 @@ default_input = login # DOOM animation fire height (1 thru 9) doom_fire_height = 6 -# DOOM animation use natural fire colors -# If false, below custom colors used -doom_default_colors = true +# DOOM animation fire spread (0 thru 4) +doom_fire_spread = 2 # DOOM animation custom top color (low intensity flames) -doom_top_color = 0x00FF0000 +doom_top_color = 0x009F2707 # DOOM animation custom middle color (medium intensity flames) -doom_middle_color = 0x00FFFF00 +doom_middle_color = 0x00C78F17 # DOOM animation custom bottom color (high intensity flames) doom_bottom_color = 0x00FFFFFF diff --git a/src/animations/Doom.zig b/src/animations/Doom.zig index 721eead..76850fa 100644 --- a/src/animations/Doom.zig +++ b/src/animations/Doom.zig @@ -7,34 +7,21 @@ const TerminalBuffer = @import("../tui/TerminalBuffer.zig"); const Doom = @This(); pub const STEPS = 12; +pub const HEIGHT_MAX = 9; +pub const SPREAD_MAX = 4; allocator: Allocator, terminal_buffer: *TerminalBuffer, buffer: []u8, height: u8, +spread: u8, fire: [STEPS + 1]Cell, -pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, fire_height: u8, default_colors: bool, top_color: u32, middle_color: u32, bottom_color: u32) !Doom { +pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, top_color: u32, middle_color: u32, bottom_color: u32, fire_height: u8, fire_spread: u8) !Doom { const buffer = try allocator.alloc(u8, terminal_buffer.width * terminal_buffer.height); initBuffer(buffer, terminal_buffer.width); - const levels = if (default_colors) - [_]Cell{ - Cell.init(' ', TerminalBuffer.Color.DEFAULT, TerminalBuffer.Color.DEFAULT), - Cell.init(0x2591, 0x009F2707, TerminalBuffer.Color.DEFAULT), - Cell.init(0x2592, 0x009F2707, TerminalBuffer.Color.DEFAULT), - Cell.init(0x2593, 0x009F2707, TerminalBuffer.Color.DEFAULT), - Cell.init(0x2588, 0x009F2707, TerminalBuffer.Color.DEFAULT), - Cell.init(0x2591, 0x00C78F17, 0x009F2707), - Cell.init(0x2592, 0x00C78F17, 0x009F2707), - Cell.init(0x2593, 0x00C78F17, 0x009F2707), - Cell.init(0x2588, 0x00C78F17, 0x009F2707), - Cell.init(0x2591, 0x00FFFFFF, 0x00C78F17), - Cell.init(0x2592, 0x00FFFFFF, 0x00C78F17), - Cell.init(0x2593, 0x00FFFFFF, 0x00C78F17), - Cell.init(0x2588, 0x00FFFFFF, 0x00C78F17), - } - else + const levels = [_]Cell{ Cell.init(' ', TerminalBuffer.Color.DEFAULT, TerminalBuffer.Color.DEFAULT), Cell.init(0x2591, top_color, TerminalBuffer.Color.DEFAULT), @@ -55,7 +42,8 @@ pub fn init(allocator: Allocator, terminal_buffer: *TerminalBuffer, fire_height: .allocator = allocator, .terminal_buffer = terminal_buffer, .buffer = buffer, - .height = @min(9, fire_height), + .height = @min(HEIGHT_MAX, fire_height), + .spread = @min(SPREAD_MAX, fire_spread), .fire = levels, }; } @@ -81,11 +69,12 @@ fn draw(self: *Doom) void { // Get index of current cell in fire level buffer const from = y * self.terminal_buffer.width + x; - // Generate random datum for fire propagation - const random = (self.terminal_buffer.random.int(u8) % 10); + // Generate random data for fire propagation + const rand_loss = self.terminal_buffer.random.intRangeAtMost(u8, 0, HEIGHT_MAX); + const rand_spread = self.terminal_buffer.random.intRangeAtMost(u8, 0, self.spread * 2); // Select semi-random target cell - const to = from -| self.terminal_buffer.width -| (random & 3) + 1; + const to = from -| self.terminal_buffer.width + self.spread -| rand_spread; const to_x = to % self.terminal_buffer.width; const to_y = to / self.terminal_buffer.width; @@ -93,9 +82,8 @@ fn draw(self: *Doom) void { const level_buf_from = self.buffer[from]; // Choose new fire level and store in level buffer - var level_buf_to = level_buf_from; - if (random >= self.height) level_buf_to -|= 1; - self.buffer[to] = @intCast(level_buf_to); + const level_buf_to = level_buf_from -| @intFromBool(rand_loss >= self.height); + self.buffer[to] = level_buf_to; // Send known fire levels to terminal buffer const from_cell = self.fire[level_buf_from]; diff --git a/src/config/Config.zig b/src/config/Config.zig index 613c55a..8b020f0 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -30,7 +30,7 @@ colormix_col2: u32 = 0x000000FF, colormix_col3: u32 = 0x20000000, default_input: Input = .login, doom_fire_height: u8 = 6, -doom_default_colors: bool = true, +doom_fire_spread: u8 = 2, doom_top_color: u32 = 0x00FF0000, doom_middle_color: u32 = 0x00FFFF00, doom_bottom_color: u32 = 0x00FFFFFF, diff --git a/src/main.zig b/src/main.zig index b14a462..fb42923 100644 --- a/src/main.zig +++ b/src/main.zig @@ -354,7 +354,7 @@ pub fn main() !void { animation = dummy.animation(); }, .doom => { - var doom = try Doom.init(allocator, &buffer, config.doom_fire_height, config.doom_default_colors, config.doom_top_color, config.doom_middle_color, config.doom_bottom_color); + var doom = try Doom.init(allocator, &buffer, config.doom_top_color, config.doom_middle_color, config.doom_bottom_color, config.doom_fire_height, config.doom_fire_spread); animation = doom.animation(); }, .matrix => {