mirror of
https://github.com/RGBCube/DOOM-fire-zig
synced 2025-07-27 17:17:45 +00:00
Make doomfire cross-platform
This commit is contained in:
parent
add37add17
commit
100a2abef5
3 changed files with 291 additions and 273 deletions
|
@ -1,5 +1,5 @@
|
||||||
# DOOMFIRE
|
# DOOMFIRE
|
||||||
Test your TTY might!
|
## Test your TTY's might!
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
@ -8,7 +8,10 @@ The doom-fire algo can push upwards of 180k a frame - results may vary! It is,
|
||||||
As a comparable, this is the younger sibling of a node variant ( https://github.com/const-void/DOOM-fire-node ).
|
As a comparable, this is the younger sibling of a node variant ( https://github.com/const-void/DOOM-fire-node ).
|
||||||
|
|
||||||
# INSTALL
|
# INSTALL
|
||||||
Tested on OX Monterey / M1 w/zig 0.9...unsure if it will work on Win or Linux, sadly, due to TIOCGWINSZ flag. No third party dependencies!
|
Tested on OX Monterey / M1 w/zig 0.9...
|
||||||
|
|
||||||
|
EDIT: Now tested on Artix Linux - links against libc to get the size of the TTY.
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
$ git clone https://github.com/const-void/DOOM-fire-zig/
|
$ git clone https://github.com/const-void/DOOM-fire-zig/
|
||||||
|
@ -22,6 +25,7 @@ $ zig build run
|
||||||
* kitty.app - great
|
* kitty.app - great
|
||||||
* Terminal.app - poor -- seems to drop framerates
|
* Terminal.app - poor -- seems to drop framerates
|
||||||
* VS Code - great
|
* VS Code - great
|
||||||
|
* Alacritty (artix linux) - great
|
||||||
|
|
||||||
# Inspiration / Credits
|
# Inspiration / Credits
|
||||||
* doom fire - https://github.com/filipedeschamps/doom-fire-algorithm, https://github.com/fabiensanglard/DoomFirePSX/blob/master/flames.html
|
* doom fire - https://github.com/filipedeschamps/doom-fire-algorithm, https://github.com/fabiensanglard/DoomFirePSX/blob/master/flames.html
|
||||||
|
|
|
@ -12,6 +12,9 @@ pub fn build(b: *std.build.Builder) void {
|
||||||
const mode = b.standardReleaseOptions();
|
const mode = b.standardReleaseOptions();
|
||||||
|
|
||||||
const exe = b.addExecutable("DOOM-fire", "src/main.zig");
|
const exe = b.addExecutable("DOOM-fire", "src/main.zig");
|
||||||
|
|
||||||
|
exe.addIncludeDir("src");
|
||||||
|
exe.linkLibC();
|
||||||
exe.setTarget(target);
|
exe.setTarget(target);
|
||||||
exe.setBuildMode(mode);
|
exe.setBuildMode(mode);
|
||||||
exe.install();
|
exe.install();
|
||||||
|
|
481
src/main.zig
481
src/main.zig
|
@ -5,13 +5,18 @@
|
||||||
//
|
//
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
// Gets the correct TIOCGWINSZ value from libc.
|
||||||
|
const c = @cImport({
|
||||||
|
@cInclude("sys/ioctl.h");
|
||||||
|
});
|
||||||
|
|
||||||
const allocator = std.heap.page_allocator;
|
const allocator = std.heap.page_allocator;
|
||||||
|
|
||||||
const stdout = std.io.getStdOut().writer();
|
const stdout = std.io.getStdOut().writer();
|
||||||
const stdin = std.io.getStdIn().reader();
|
const stdin = std.io.getStdIn().reader();
|
||||||
|
|
||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
// Tested on M1 osx12.1
|
// Tested on M1 osx12.1 + Linux
|
||||||
// fast - vs code terminal
|
// fast - vs code terminal
|
||||||
// slow - Terminal.app
|
// slow - Terminal.app
|
||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
|
@ -42,7 +47,7 @@ const stdin = std.io.getStdIn().reader();
|
||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
|
|
||||||
//// consts, vars, settings
|
//// consts, vars, settings
|
||||||
var rand:std.rand.Random = undefined;
|
var rand: std.rand.Random = undefined;
|
||||||
|
|
||||||
//// functions
|
//// functions
|
||||||
|
|
||||||
|
@ -59,14 +64,16 @@ pub fn initRNG() !void {
|
||||||
|
|
||||||
// print
|
// print
|
||||||
pub fn emit(s: []const u8) void {
|
pub fn emit(s: []const u8) void {
|
||||||
const sz=stdout.write(s) catch unreachable;
|
const sz = stdout.write(s) catch unreachable;
|
||||||
if (sz==0) {return;} // cauze I c
|
if (sz == 0) {
|
||||||
|
return;
|
||||||
|
} // cauze I c
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// format a string then print
|
// format a string then print
|
||||||
pub fn emit_fmt(comptime s: []const u8, args: anytype) void {
|
pub fn emit_fmt(comptime s: []const u8, args: anytype) void {
|
||||||
const t=std.fmt.allocPrint(allocator,s,args) catch unreachable;
|
const t = std.fmt.allocPrint(allocator, s, args) catch unreachable;
|
||||||
defer allocator.free(t);
|
defer allocator.free(t);
|
||||||
emit(t);
|
emit(t);
|
||||||
}
|
}
|
||||||
|
@ -77,63 +84,63 @@ pub fn emit_fmt(comptime s: []const u8, args: anytype) void {
|
||||||
|
|
||||||
//// Settings
|
//// Settings
|
||||||
|
|
||||||
//OSX specific ... maybe
|
// Get this from libc instead of some random value.
|
||||||
const TIOCGWINSZ=0x40087468; //ioctl flag
|
const TIOCGWINSZ = c.TIOCGWINSZ;
|
||||||
|
|
||||||
//term size
|
//term size
|
||||||
const TermSz = struct { height: usize, width: usize };
|
const TermSz = struct { height: usize, width: usize };
|
||||||
var term_sz:TermSz = .{ .height=0, .width=0 }; // set via initTermSz
|
var term_sz: TermSz = .{ .height = 0, .width = 0 }; // set via initTermSz
|
||||||
|
|
||||||
//ansi escape codes
|
//ansi escape codes
|
||||||
const esc = "\x1B";
|
const esc = "\x1B";
|
||||||
const csi = esc++"[";
|
const csi = esc ++ "[";
|
||||||
|
|
||||||
const cursor_save=esc++"7";
|
const cursor_save = esc ++ "7";
|
||||||
const cursor_load=esc++"8";
|
const cursor_load = esc ++ "8";
|
||||||
|
|
||||||
const cursor_show=csi++"?25h"; //h=high
|
const cursor_show = csi ++ "?25h"; //h=high
|
||||||
const cursor_hide=csi++"?25l"; //l=low
|
const cursor_hide = csi ++ "?25l"; //l=low
|
||||||
const cursor_home=csi++"1;1H"; //1,1
|
const cursor_home = csi ++ "1;1H"; //1,1
|
||||||
|
|
||||||
const screen_clear=csi++"2J";
|
const screen_clear = csi ++ "2J";
|
||||||
const screen_buf_on=csi++"?1049h"; //h=high
|
const screen_buf_on = csi ++ "?1049h"; //h=high
|
||||||
const screen_buf_off=csi++"?1049l"; //l=low
|
const screen_buf_off = csi ++ "?1049l"; //l=low
|
||||||
|
|
||||||
const line_clear_to_eol=csi++"0K";
|
const line_clear_to_eol = csi ++ "0K";
|
||||||
|
|
||||||
const color_reset=csi++"0m";
|
const color_reset = csi ++ "0m";
|
||||||
const color_fg="38;5;";
|
const color_fg = "38;5;";
|
||||||
const color_bg="48;5;";
|
const color_bg = "48;5;";
|
||||||
|
|
||||||
const color_fg_def=csi++color_fg++"15m"; // white
|
const color_fg_def = csi ++ color_fg ++ "15m"; // white
|
||||||
const color_bg_def=csi++color_bg++"0m"; // black
|
const color_bg_def = csi ++ color_bg ++ "0m"; // black
|
||||||
const color_def=color_bg_def++color_fg_def;
|
const color_def = color_bg_def ++ color_fg_def;
|
||||||
const color_italic=csi++"3m";
|
const color_italic = csi ++ "3m";
|
||||||
const color_not_italic=csi++"23m";
|
const color_not_italic = csi ++ "23m";
|
||||||
|
|
||||||
const term_on=screen_buf_on++cursor_hide++cursor_home++screen_clear++color_def;
|
const term_on = screen_buf_on ++ cursor_hide ++ cursor_home ++ screen_clear ++ color_def;
|
||||||
const term_off=screen_buf_off++cursor_show++nl;
|
const term_off = screen_buf_off ++ cursor_show ++ nl;
|
||||||
|
|
||||||
//handy characters
|
//handy characters
|
||||||
const nl="\n";
|
const nl = "\n";
|
||||||
const sep='▏';
|
const sep = '▏';
|
||||||
|
|
||||||
//colors
|
//colors
|
||||||
const MAX_COLOR=256;
|
const MAX_COLOR = 256;
|
||||||
const LAST_COLOR=MAX_COLOR-1;
|
const LAST_COLOR = MAX_COLOR - 1;
|
||||||
|
|
||||||
var fg:[MAX_COLOR][]u8 = undefined;
|
var fg: [MAX_COLOR][]u8 = undefined;
|
||||||
var bg:[MAX_COLOR][]u8 = undefined;
|
var bg: [MAX_COLOR][]u8 = undefined;
|
||||||
|
|
||||||
//// functions
|
//// functions
|
||||||
|
|
||||||
// cache fg/bg ansi codes
|
// cache fg/bg ansi codes
|
||||||
pub fn initColor() void {
|
pub fn initColor() void {
|
||||||
var color_idx:u16=0;
|
var color_idx: u16 = 0;
|
||||||
while (color_idx<MAX_COLOR) {
|
while (color_idx < MAX_COLOR) {
|
||||||
fg[color_idx]=std.fmt.allocPrint(allocator,"{s}38;5;{d}m",.{csi,color_idx}) catch unreachable;
|
fg[color_idx] = std.fmt.allocPrint(allocator, "{s}38;5;{d}m", .{ csi, color_idx }) catch unreachable;
|
||||||
bg[color_idx]=std.fmt.allocPrint(allocator,"{s}48;5;{d}m",.{csi,color_idx}) catch unreachable;
|
bg[color_idx] = std.fmt.allocPrint(allocator, "{s}48;5;{d}m", .{ csi, color_idx }) catch unreachable;
|
||||||
color_idx+=1;
|
color_idx += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,18 +149,20 @@ pub fn initColor() void {
|
||||||
|
|
||||||
//get terminal size given a tty
|
//get terminal size given a tty
|
||||||
pub fn getTermSz(tty: std.os.fd_t) !TermSz {
|
pub fn getTermSz(tty: std.os.fd_t) !TermSz {
|
||||||
var winsz = std.os.system.winsize {
|
// Get this struct from libc instead of Zig's std. I shall add this struct regardless so you can call std.os.system.winsize.
|
||||||
.ws_col=0, .ws_row=0,
|
// This is hacky and bad.
|
||||||
.ws_xpixel=0, .ws_ypixel=0
|
var winsz = c.winsize{ .ws_col = 0, .ws_row = 0, .ws_xpixel = 0, .ws_ypixel = 0 };
|
||||||
};
|
const rv = std.os.system.ioctl(tty, TIOCGWINSZ, @ptrToInt(&winsz));
|
||||||
const rv=std.os.system.ioctl(tty,TIOCGWINSZ, @ptrToInt(&winsz));
|
const err = std.os.errno(rv);
|
||||||
const err=std.os.errno(rv);
|
if (rv == 0) {
|
||||||
if (rv==0) { return TermSz{ .height = winsz.ws_row, .width = winsz.ws_col }; }
|
return TermSz{ .height = winsz.ws_row, .width = winsz.ws_col };
|
||||||
else {return std.os.unexpectedErrno(err);}
|
} else {
|
||||||
|
return std.os.unexpectedErrno(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initTermSize() !void {
|
pub fn initTermSize() !void {
|
||||||
term_sz=try getTermSz(stdout.context.handle);
|
term_sz = try getTermSz(stdout.context.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initTerm() !void {
|
pub fn initTerm() !void {
|
||||||
|
@ -179,7 +188,7 @@ pub fn pause() void {
|
||||||
|
|
||||||
emit(color_reset);
|
emit(color_reset);
|
||||||
emit("Press return to continue...");
|
emit("Press return to continue...");
|
||||||
var b:u8 = undefined;
|
var b: u8 = undefined;
|
||||||
b = stdin.readByte() catch undefined;
|
b = stdin.readByte() catch undefined;
|
||||||
|
|
||||||
if (b == 'q') {
|
if (b == 'q') {
|
||||||
|
@ -189,7 +198,6 @@ pub fn pause() void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Part I - Terminal Size Check
|
/// Part I - Terminal Size Check
|
||||||
/// showTermCap() needs about 120x22; if screen is too small, give user a chance to abort and try again.
|
/// showTermCap() needs about 120x22; if screen is too small, give user a chance to abort and try again.
|
||||||
///
|
///
|
||||||
|
@ -198,28 +206,38 @@ pub fn pause() void {
|
||||||
|
|
||||||
// do nothing if term sz is big enough
|
// do nothing if term sz is big enough
|
||||||
pub fn checkTermSz() void {
|
pub fn checkTermSz() void {
|
||||||
const min_w=120;
|
const min_w = 120;
|
||||||
const min_h=22;
|
const min_h = 22;
|
||||||
var w_ok=true;
|
var w_ok = true;
|
||||||
var h_ok=true;
|
var h_ok = true;
|
||||||
|
|
||||||
// chk cur < min
|
// chk cur < min
|
||||||
if (term_sz.width<min_w) { w_ok=false; }
|
if (term_sz.width < min_w) {
|
||||||
if (term_sz.height<min_h) { h_ok=false; }
|
w_ok = false;
|
||||||
|
}
|
||||||
|
if (term_sz.height < min_h) {
|
||||||
|
h_ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (w_ok and h_ok) { return; }
|
if (w_ok and h_ok) {
|
||||||
else {
|
return;
|
||||||
|
} else {
|
||||||
//screen is too small
|
//screen is too small
|
||||||
|
|
||||||
//red text
|
//red text
|
||||||
emit(fg[9]);
|
emit(fg[9]);
|
||||||
|
|
||||||
//check conditions
|
//check conditions
|
||||||
if (w_ok and !h_ok) { emit_fmt("Screen may be too short - height is {d} and need {d}.",.{term_sz.height, min_h}); }
|
if (w_ok and !h_ok) {
|
||||||
else if (!w_ok and h_ok) { emit_fmt("Screen may be too narrow - width is {d} and need {d}.",.{term_sz.width, min_w}); }
|
emit_fmt("Screen may be too short - height is {d} and need {d}.", .{ term_sz.height, min_h });
|
||||||
else { emit_fmt("Screen is too small - have {d} x {d} and need {d} x {d}",.{term_sz.width, term_sz.height, min_w, min_h}); }
|
} else if (!w_ok and h_ok) {
|
||||||
|
emit_fmt("Screen may be too narrow - width is {d} and need {d}.", .{ term_sz.width, min_w });
|
||||||
|
} else {
|
||||||
|
emit_fmt("Screen is too small - have {d} x {d} and need {d} x {d}", .{ term_sz.width, term_sz.height, min_w, min_h });
|
||||||
|
}
|
||||||
|
|
||||||
emit(nl);emit(nl);
|
emit(nl);
|
||||||
|
emit(nl);
|
||||||
|
|
||||||
//warn user w/white on red
|
//warn user w/white on red
|
||||||
emit(bg[1]);
|
emit(bg[1]);
|
||||||
|
@ -244,14 +262,13 @@ pub fn checkTermSz() void {
|
||||||
/// Since user terminals vary in capabilities, handy to have a screen that renders ACTUAL colors
|
/// Since user terminals vary in capabilities, handy to have a screen that renders ACTUAL colors
|
||||||
/// and exercises various terminal commands prior to DOOM fire.
|
/// and exercises various terminal commands prior to DOOM fire.
|
||||||
///
|
///
|
||||||
|
|
||||||
pub fn showTermSz() void {
|
pub fn showTermSz() void {
|
||||||
//todo - show os, os ver, zig ver
|
//todo - show os, os ver, zig ver
|
||||||
emit_fmt("Screen size: {d}w x {d}h\n\n", .{term_sz.width, term_sz.height});
|
emit_fmt("Screen size: {d}w x {d}h\n\n", .{ term_sz.width, term_sz.height });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn showLabel(label:[]const u8) void {
|
pub fn showLabel(label: []const u8) void {
|
||||||
emit_fmt("{s}{s}:\n",.{color_def,label});
|
emit_fmt("{s}{s}:\n", .{ color_def, label });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn showStdColors() void {
|
pub fn showStdColors() void {
|
||||||
|
@ -259,23 +276,26 @@ pub fn showStdColors() void {
|
||||||
|
|
||||||
//first 8 colors (standard)
|
//first 8 colors (standard)
|
||||||
emit(fg[15]);
|
emit(fg[15]);
|
||||||
var color_idx:u8=0;
|
var color_idx: u8 = 0;
|
||||||
while (color_idx<8) {
|
while (color_idx < 8) {
|
||||||
defer color_idx+=1;
|
defer color_idx += 1;
|
||||||
emit(bg[color_idx]);
|
emit(bg[color_idx]);
|
||||||
if (color_idx==7) { emit(fg[0]); }
|
if (color_idx == 7) {
|
||||||
emit_fmt("{u} {d:2} ", .{sep,color_idx});
|
emit(fg[0]);
|
||||||
|
}
|
||||||
|
emit_fmt("{u} {d:2} ", .{ sep, color_idx });
|
||||||
}
|
}
|
||||||
emit(nl);
|
emit(nl);
|
||||||
|
|
||||||
//next 8 colors ("hilight")
|
//next 8 colors ("hilight")
|
||||||
emit(fg[15]);
|
emit(fg[15]);
|
||||||
while (color_idx<16) {
|
while (color_idx < 16) {
|
||||||
defer color_idx+=1;
|
defer color_idx += 1;
|
||||||
emit(bg[color_idx]);
|
emit(bg[color_idx]);
|
||||||
if (color_idx==15) { emit(fg[0]); }
|
if (color_idx == 15) {
|
||||||
emit_fmt("{u} {d:2} ", .{sep,color_idx});
|
emit(fg[0]);
|
||||||
|
}
|
||||||
|
emit_fmt("{u} {d:2} ", .{ sep, color_idx });
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(nl);
|
emit(nl);
|
||||||
|
@ -285,37 +305,36 @@ pub fn showStdColors() void {
|
||||||
pub fn show216Colors() void {
|
pub fn show216Colors() void {
|
||||||
showLabel("216 colors");
|
showLabel("216 colors");
|
||||||
|
|
||||||
var color_addendum:u8=0;
|
var color_addendum: u8 = 0;
|
||||||
var bg_idx:u8=0;
|
var bg_idx: u8 = 0;
|
||||||
var fg_idx:u8=0;
|
var fg_idx: u8 = 0;
|
||||||
|
|
||||||
//show remaining of colors in 6 blocks of 6x6
|
//show remaining of colors in 6 blocks of 6x6
|
||||||
|
|
||||||
// 6 rows of color
|
// 6 rows of color
|
||||||
var color_shift:u8=0;
|
var color_shift: u8 = 0;
|
||||||
while (color_shift<6) {
|
while (color_shift < 6) {
|
||||||
defer color_shift+=1;
|
defer color_shift += 1;
|
||||||
|
|
||||||
color_addendum=color_shift*36+16;
|
color_addendum = color_shift * 36 + 16;
|
||||||
|
|
||||||
// colors are pre-organized into blocks
|
// colors are pre-organized into blocks
|
||||||
var color_idx:u8=0;
|
var color_idx: u8 = 0;
|
||||||
while(color_idx<36) {
|
while (color_idx < 36) {
|
||||||
defer color_idx+=1;
|
defer color_idx += 1;
|
||||||
bg_idx=color_idx+color_addendum;
|
bg_idx = color_idx + color_addendum;
|
||||||
|
|
||||||
// invert color id for readability
|
// invert color id for readability
|
||||||
if (color_idx>17) {
|
if (color_idx > 17) {
|
||||||
fg_idx=0;
|
fg_idx = 0;
|
||||||
}
|
} else {
|
||||||
else {
|
fg_idx = 15;
|
||||||
fg_idx=15;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// display color
|
// display color
|
||||||
emit(bg[bg_idx]);
|
emit(bg[bg_idx]);
|
||||||
emit(fg[fg_idx]);
|
emit(fg[fg_idx]);
|
||||||
emit_fmt("{d:3}",.{bg_idx});
|
emit_fmt("{d:3}", .{bg_idx});
|
||||||
}
|
}
|
||||||
emit(nl);
|
emit(nl);
|
||||||
}
|
}
|
||||||
|
@ -325,20 +344,20 @@ pub fn show216Colors() void {
|
||||||
pub fn showGrayscale() void {
|
pub fn showGrayscale() void {
|
||||||
showLabel("Grayscale");
|
showLabel("Grayscale");
|
||||||
|
|
||||||
var fg_idx:u8=15;
|
var fg_idx: u8 = 15;
|
||||||
emit(fg[fg_idx]);
|
emit(fg[fg_idx]);
|
||||||
|
|
||||||
var bg_idx:u16=232;
|
var bg_idx: u16 = 232;
|
||||||
while (bg_idx<256) {
|
while (bg_idx < 256) {
|
||||||
defer bg_idx+=1;
|
defer bg_idx += 1;
|
||||||
|
|
||||||
if (bg_idx>243) {
|
if (bg_idx > 243) {
|
||||||
fg_idx=0;
|
fg_idx = 0;
|
||||||
emit(fg[fg_idx]);
|
emit(fg[fg_idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(bg[bg_idx]);
|
emit(bg[bg_idx]);
|
||||||
emit_fmt("{u}{d} ",.{sep,bg_idx});
|
emit_fmt("{u}{d} ", .{ sep, bg_idx });
|
||||||
}
|
}
|
||||||
emit(nl);
|
emit(nl);
|
||||||
|
|
||||||
|
@ -349,9 +368,9 @@ pub fn showGrayscale() void {
|
||||||
|
|
||||||
pub fn scrollMarquee() void {
|
pub fn scrollMarquee() void {
|
||||||
//marquee - 4 lines of yellowish background
|
//marquee - 4 lines of yellowish background
|
||||||
const bg_idx:u8=222;
|
const bg_idx: u8 = 222;
|
||||||
const marquee_row=line_clear_to_eol++nl;
|
const marquee_row = line_clear_to_eol ++ nl;
|
||||||
const marquee_bg=marquee_row++marquee_row++marquee_row++marquee_row;
|
const marquee_bg = marquee_row ++ marquee_row ++ marquee_row ++ marquee_row;
|
||||||
|
|
||||||
//init marquee background
|
//init marquee background
|
||||||
emit(cursor_save);
|
emit(cursor_save);
|
||||||
|
@ -359,31 +378,23 @@ pub fn scrollMarquee() void {
|
||||||
emit(marquee_bg);
|
emit(marquee_bg);
|
||||||
|
|
||||||
//quotes - will confirm animations are working on current terminal
|
//quotes - will confirm animations are working on current terminal
|
||||||
const txt =[_][]const u8{
|
const txt = [_][]const u8{ " Things move along so rapidly nowadays that people saying " ++ color_italic ++ "It can't be done" ++ color_not_italic ++ " are always being interrupted", " by somebody doing it. " ++ color_italic ++ "-- Puck, 1902" ++ color_not_italic, " Test your might!", " " ++ color_italic ++ "-- Mortal Kombat" ++ color_not_italic, " How much is the fish?", " " ++ color_italic ++ "-- Scooter" ++ color_not_italic };
|
||||||
" Things move along so rapidly nowadays that people saying "++color_italic++"It can't be done"++color_not_italic++" are always being interrupted",
|
const txt_len: u8 = txt.len / 2; // print two rows at a time
|
||||||
" by somebody doing it. "++color_italic++"-- Puck, 1902"++color_not_italic,
|
|
||||||
|
|
||||||
" Test your might!",
|
|
||||||
" "++color_italic++"-- Mortal Kombat"++color_not_italic,
|
|
||||||
|
|
||||||
" How much is the fish?",
|
|
||||||
" "++color_italic++"-- Scooter"++color_not_italic};
|
|
||||||
const txt_len:u8 = txt.len/2; // print two rows at a time
|
|
||||||
|
|
||||||
//fade txt in and out
|
//fade txt in and out
|
||||||
const fade_seq=[_]u8{222,221,220,215,214,184,178,130,235,58,16};
|
const fade_seq = [_]u8{ 222, 221, 220, 215, 214, 184, 178, 130, 235, 58, 16 };
|
||||||
const fade_len:u8=fade_seq.len;
|
const fade_len: u8 = fade_seq.len;
|
||||||
|
|
||||||
var fade_idx:u8=0;
|
var fade_idx: u8 = 0;
|
||||||
var txt_idx:u8=0;
|
var txt_idx: u8 = 0;
|
||||||
|
|
||||||
while (txt_idx<txt_len) {
|
while (txt_idx < txt_len) {
|
||||||
defer txt_idx+=1;
|
defer txt_idx += 1;
|
||||||
|
|
||||||
//fade in
|
//fade in
|
||||||
fade_idx=0;
|
fade_idx = 0;
|
||||||
while (fade_idx<fade_len) {
|
while (fade_idx < fade_len) {
|
||||||
defer fade_idx+=1;
|
defer fade_idx += 1;
|
||||||
|
|
||||||
//reset to 1,1 of marquee
|
//reset to 1,1 of marquee
|
||||||
emit(cursor_load);
|
emit(cursor_load);
|
||||||
|
@ -392,10 +403,10 @@ pub fn scrollMarquee() void {
|
||||||
|
|
||||||
//print marquee txt
|
//print marquee txt
|
||||||
emit(fg[fade_seq[fade_idx]]);
|
emit(fg[fade_seq[fade_idx]]);
|
||||||
emit(txt[txt_idx*2]);
|
emit(txt[txt_idx * 2]);
|
||||||
emit(line_clear_to_eol);
|
emit(line_clear_to_eol);
|
||||||
emit(nl);
|
emit(nl);
|
||||||
emit(txt[txt_idx*2+1]);
|
emit(txt[txt_idx * 2 + 1]);
|
||||||
emit(line_clear_to_eol);
|
emit(line_clear_to_eol);
|
||||||
emit(nl);
|
emit(nl);
|
||||||
|
|
||||||
|
@ -405,23 +416,22 @@ pub fn scrollMarquee() void {
|
||||||
//let quote chill for a second
|
//let quote chill for a second
|
||||||
std.time.sleep(1000 * std.time.ns_per_ms);
|
std.time.sleep(1000 * std.time.ns_per_ms);
|
||||||
|
|
||||||
|
|
||||||
//fade out
|
//fade out
|
||||||
fade_idx=fade_len-1;
|
fade_idx = fade_len - 1;
|
||||||
while (fade_idx>0) {
|
while (fade_idx > 0) {
|
||||||
defer fade_idx-=1;
|
defer fade_idx -= 1;
|
||||||
|
|
||||||
//reset to 1,1 of marquee
|
//reset to 1,1 of marquee
|
||||||
emit(cursor_load);
|
emit(cursor_load);
|
||||||
emit(bg[bg_idx]);
|
emit(bg[bg_idx]);
|
||||||
emit(nl);
|
emit(nl);
|
||||||
|
|
||||||
//print marquee txt
|
//print marquee txt
|
||||||
emit(fg[fade_seq[fade_idx]]);
|
emit(fg[fade_seq[fade_idx]]);
|
||||||
emit(txt[txt_idx*2]);
|
emit(txt[txt_idx * 2]);
|
||||||
emit(line_clear_to_eol);
|
emit(line_clear_to_eol);
|
||||||
emit(nl);
|
emit(nl);
|
||||||
emit(txt[txt_idx*2+1]);
|
emit(txt[txt_idx * 2 + 1]);
|
||||||
emit(line_clear_to_eol);
|
emit(line_clear_to_eol);
|
||||||
emit(nl);
|
emit(nl);
|
||||||
std.time.sleep(10 * std.time.ns_per_ms);
|
std.time.sleep(10 * std.time.ns_per_ms);
|
||||||
|
@ -446,109 +456,112 @@ pub fn showTermCap() void {
|
||||||
/// Below - moderately faster
|
/// Below - moderately faster
|
||||||
|
|
||||||
//pixel character
|
//pixel character
|
||||||
const px="▀";
|
const px = "▀";
|
||||||
|
|
||||||
//bs = buffer string
|
//bs = buffer string
|
||||||
var bs:[]u8=undefined;
|
var bs: []u8 = undefined;
|
||||||
var bs_idx:u32=0;
|
var bs_idx: u32 = 0;
|
||||||
var bs_len:u32=0;
|
var bs_len: u32 = 0;
|
||||||
var bs_sz_min:u32=0;
|
var bs_sz_min: u32 = 0;
|
||||||
var bs_sz_max:u32=0;
|
var bs_sz_max: u32 = 0;
|
||||||
var bs_sz_avg:u32=0;
|
var bs_sz_avg: u32 = 0;
|
||||||
var bs_frame_tic:u32=0;
|
var bs_frame_tic: u32 = 0;
|
||||||
var t_start:i64=0;
|
var t_start: i64 = 0;
|
||||||
var t_now:i64=0;
|
var t_now: i64 = 0;
|
||||||
var t_dur:f64=0.0;
|
var t_dur: f64 = 0.0;
|
||||||
var fps:f64=0.0;
|
var fps: f64 = 0.0;
|
||||||
|
|
||||||
|
|
||||||
pub fn initBuf() void {
|
pub fn initBuf() void {
|
||||||
//some lazy guesswork to make sure we have enough of a buffer to render DOOM fire.
|
//some lazy guesswork to make sure we have enough of a buffer to render DOOM fire.
|
||||||
const px_char_sz=px.len;
|
const px_char_sz = px.len;
|
||||||
const px_color_sz=bg[LAST_COLOR].len+fg[LAST_COLOR].len;
|
const px_color_sz = bg[LAST_COLOR].len + fg[LAST_COLOR].len;
|
||||||
const px_sz=px_color_sz+px_char_sz;
|
const px_sz = px_color_sz + px_char_sz;
|
||||||
const screen_sz:u64=@as(u64,px_sz*term_sz.width*term_sz.width);
|
const screen_sz: u64 = @as(u64, px_sz * term_sz.width * term_sz.width);
|
||||||
const overflow_sz:u64=px_char_sz*100;
|
const overflow_sz: u64 = px_char_sz * 100;
|
||||||
const bs_sz:u64=screen_sz+overflow_sz;
|
const bs_sz: u64 = screen_sz + overflow_sz;
|
||||||
|
|
||||||
bs=allocator.alloc(u8,bs_sz*2) catch unreachable;
|
bs = allocator.alloc(u8, bs_sz * 2) catch unreachable;
|
||||||
t_start=std.time.milliTimestamp();
|
t_start = std.time.milliTimestamp();
|
||||||
resetBuf();
|
resetBuf();
|
||||||
}
|
}
|
||||||
|
|
||||||
//reset buffer indexes to start of buffer
|
//reset buffer indexes to start of buffer
|
||||||
pub fn resetBuf() void {
|
pub fn resetBuf() void {
|
||||||
bs_idx=0;
|
bs_idx = 0;
|
||||||
bs_len=0;
|
bs_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//copy input string to buffer string
|
//copy input string to buffer string
|
||||||
pub fn drawBuf(s:[]const u8) void {
|
pub fn drawBuf(s: []const u8) void {
|
||||||
for (s) |b| {
|
for (s) |b| {
|
||||||
bs[bs_idx] = b;
|
bs[bs_idx] = b;
|
||||||
bs_idx+=1;
|
bs_idx += 1;
|
||||||
bs_len+=1;
|
bs_len += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//print buffer to string...can be a decent amount of text!
|
//print buffer to string...can be a decent amount of text!
|
||||||
pub fn paintBuf() void {
|
pub fn paintBuf() void {
|
||||||
emit(bs[0..bs_len-1]);
|
emit(bs[0 .. bs_len - 1]);
|
||||||
t_now=std.time.milliTimestamp();
|
t_now = std.time.milliTimestamp();
|
||||||
bs_frame_tic+=1;
|
bs_frame_tic += 1;
|
||||||
if (bs_sz_min==0) {
|
if (bs_sz_min == 0) {
|
||||||
//first frame
|
//first frame
|
||||||
bs_sz_min=bs_len;
|
bs_sz_min = bs_len;
|
||||||
bs_sz_max=bs_len;
|
bs_sz_max = bs_len;
|
||||||
bs_sz_avg=bs_len;
|
bs_sz_avg = bs_len;
|
||||||
}
|
} else {
|
||||||
else {
|
if (bs_len < bs_sz_min) {
|
||||||
if( bs_len < bs_sz_min) { bs_sz_min=bs_len; }
|
bs_sz_min = bs_len;
|
||||||
if( bs_len > bs_sz_max) { bs_sz_max=bs_len; }
|
}
|
||||||
bs_sz_avg=bs_sz_avg*(bs_frame_tic-1)/bs_frame_tic+bs_len/bs_frame_tic;
|
if (bs_len > bs_sz_max) {
|
||||||
|
bs_sz_max = bs_len;
|
||||||
|
}
|
||||||
|
bs_sz_avg = bs_sz_avg * (bs_frame_tic - 1) / bs_frame_tic + bs_len / bs_frame_tic;
|
||||||
}
|
}
|
||||||
|
|
||||||
t_dur=@intToFloat(f64,t_now-t_start)/1000.0;
|
t_dur = @intToFloat(f64, t_now - t_start) / 1000.0;
|
||||||
fps=@intToFloat(f64,bs_frame_tic)/t_dur;
|
fps = @intToFloat(f64, bs_frame_tic) / t_dur;
|
||||||
|
|
||||||
emit(fg[0]);
|
emit(fg[0]);
|
||||||
emit_fmt("mem: {s:.2} min / {s:.2} avg / {s:.2} max [ {d:.2} fps ]",.{std.fmt.fmtIntSizeBin(bs_sz_min), std.fmt.fmtIntSizeBin(bs_sz_avg), std.fmt.fmtIntSizeBin(bs_sz_max), fps});
|
emit_fmt("mem: {s:.2} min / {s:.2} avg / {s:.2} max [ {d:.2} fps ]", .{ std.fmt.fmtIntSizeBin(bs_sz_min), std.fmt.fmtIntSizeBin(bs_sz_avg), std.fmt.fmtIntSizeBin(bs_sz_max), fps });
|
||||||
}
|
}
|
||||||
|
|
||||||
// initBuf(); defer freeBuf();
|
// initBuf(); defer freeBuf();
|
||||||
pub fn freeBuf() void { allocator.free(bs); }
|
pub fn freeBuf() void {
|
||||||
|
allocator.free(bs);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn showDoomFire() void {
|
pub fn showDoomFire() void {
|
||||||
//term size => fire size
|
//term size => fire size
|
||||||
const FIRE_H:u16=@intCast(u16,term_sz.height)*2;
|
const FIRE_H: u16 = @intCast(u16, term_sz.height) * 2;
|
||||||
const FIRE_W:u16=@intCast(u16,term_sz.width);
|
const FIRE_W: u16 = @intCast(u16, term_sz.width);
|
||||||
const FIRE_SZ:u16=FIRE_H*FIRE_W;
|
const FIRE_SZ: u16 = FIRE_H * FIRE_W;
|
||||||
const FIRE_LAST_ROW:u16=(FIRE_H-1)*FIRE_W;
|
const FIRE_LAST_ROW: u16 = (FIRE_H - 1) * FIRE_W;
|
||||||
|
|
||||||
//colors - tinker w/palette as needed!
|
//colors - tinker w/palette as needed!
|
||||||
const fire_palette=[_]u8{0,233,234,52,53,88,89,94,95,96,130,131,132,133,172,214,215,220,220,221,3,226,227,230,195,230};
|
const fire_palette = [_]u8{ 0, 233, 234, 52, 53, 88, 89, 94, 95, 96, 130, 131, 132, 133, 172, 214, 215, 220, 220, 221, 3, 226, 227, 230, 195, 230 };
|
||||||
const fire_black:u8=0;
|
const fire_black: u8 = 0;
|
||||||
const fire_white:u8=fire_palette.len-1;
|
const fire_white: u8 = fire_palette.len - 1;
|
||||||
|
|
||||||
//screen buf default color is black
|
//screen buf default color is black
|
||||||
var screen_buf:[]u8=undefined; //{fire_black}**FIRE_SZ;
|
var screen_buf: []u8 = undefined; //{fire_black}**FIRE_SZ;
|
||||||
screen_buf=allocator.alloc(u8,FIRE_SZ) catch unreachable;
|
screen_buf = allocator.alloc(u8, FIRE_SZ) catch unreachable;
|
||||||
defer allocator.free(screen_buf);
|
defer allocator.free(screen_buf);
|
||||||
|
|
||||||
//init buffer
|
//init buffer
|
||||||
var buf_idx:u16=0;
|
var buf_idx: u16 = 0;
|
||||||
while(buf_idx<FIRE_SZ) {
|
while (buf_idx < FIRE_SZ) {
|
||||||
defer buf_idx+=1;
|
defer buf_idx += 1;
|
||||||
|
|
||||||
screen_buf[buf_idx]=fire_black;
|
screen_buf[buf_idx] = fire_black;
|
||||||
}
|
}
|
||||||
|
|
||||||
//last row is white...white is "fire source"
|
//last row is white...white is "fire source"
|
||||||
buf_idx=0;
|
buf_idx = 0;
|
||||||
while (buf_idx<FIRE_W) {
|
while (buf_idx < FIRE_W) {
|
||||||
defer buf_idx+=1;
|
defer buf_idx += 1;
|
||||||
screen_buf[FIRE_LAST_ROW+buf_idx]=fire_white;
|
screen_buf[FIRE_LAST_ROW + buf_idx] = fire_white;
|
||||||
}
|
}
|
||||||
|
|
||||||
//reset terminal
|
//reset terminal
|
||||||
|
@ -559,60 +572,59 @@ pub fn showDoomFire() void {
|
||||||
|
|
||||||
//scope cache ////////////////////
|
//scope cache ////////////////////
|
||||||
//scope cache - update fire buf
|
//scope cache - update fire buf
|
||||||
var doFire_x:u16=0;
|
var doFire_x: u16 = 0;
|
||||||
var doFire_y:u16=0;
|
var doFire_y: u16 = 0;
|
||||||
var doFire_idx:u16=0;
|
var doFire_idx: u16 = 0;
|
||||||
|
|
||||||
//scope cache - spread fire
|
//scope cache - spread fire
|
||||||
var spread_px:u8=0;
|
var spread_px: u8 = 0;
|
||||||
var spread_rnd_idx:u8=0;
|
var spread_rnd_idx: u8 = 0;
|
||||||
var spread_dst:u16=0;
|
var spread_dst: u16 = 0;
|
||||||
|
|
||||||
//scope cache - frame reset
|
//scope cache - frame reset
|
||||||
const init_frame=std.fmt.allocPrint(allocator,"{s}{s}{s}",.{cursor_home,bg[0],fg[0]}) catch unreachable;
|
const init_frame = std.fmt.allocPrint(allocator, "{s}{s}{s}", .{ cursor_home, bg[0], fg[0] }) catch unreachable;
|
||||||
defer allocator.free(init_frame);
|
defer allocator.free(init_frame);
|
||||||
|
|
||||||
//scope cache - fire 2 screen buffer
|
//scope cache - fire 2 screen buffer
|
||||||
var frame_x:u16=0;
|
var frame_x: u16 = 0;
|
||||||
var frame_y:u16=0;
|
var frame_y: u16 = 0;
|
||||||
var px_hi:u8=fire_black;
|
var px_hi: u8 = fire_black;
|
||||||
var px_lo:u8=fire_black;
|
var px_lo: u8 = fire_black;
|
||||||
var px_prev_hi=px_hi;
|
var px_prev_hi = px_hi;
|
||||||
var px_prev_lo=px_lo;
|
var px_prev_lo = px_lo;
|
||||||
|
|
||||||
//get to work!
|
//get to work!
|
||||||
initBuf();
|
initBuf();
|
||||||
defer freeBuf();
|
defer freeBuf();
|
||||||
|
|
||||||
//when there is an ez way to poll for key stroke...do that. for now, ctrl+c!
|
//when there is an ez way to poll for key stroke...do that. for now, ctrl+c!
|
||||||
var ok=true;
|
var ok = true;
|
||||||
while(ok){
|
while (ok) {
|
||||||
|
|
||||||
//update fire buf
|
//update fire buf
|
||||||
doFire_x=0;
|
doFire_x = 0;
|
||||||
while(doFire_x<FIRE_W) {
|
while (doFire_x < FIRE_W) {
|
||||||
defer doFire_x+=1;
|
defer doFire_x += 1;
|
||||||
|
|
||||||
doFire_y=0;
|
doFire_y = 0;
|
||||||
while(doFire_y<FIRE_H) {
|
while (doFire_y < FIRE_H) {
|
||||||
defer doFire_y+=1;
|
defer doFire_y += 1;
|
||||||
|
|
||||||
doFire_idx=doFire_y*FIRE_W+doFire_x;
|
doFire_idx = doFire_y * FIRE_W + doFire_x;
|
||||||
|
|
||||||
//spread fire
|
//spread fire
|
||||||
spread_px = screen_buf[doFire_idx];
|
spread_px = screen_buf[doFire_idx];
|
||||||
|
|
||||||
//bounds checking
|
//bounds checking
|
||||||
if ( (spread_px==0) and (doFire_idx>=FIRE_W) ) {
|
if ((spread_px == 0) and (doFire_idx >= FIRE_W)) {
|
||||||
screen_buf[doFire_idx-FIRE_W]=0;
|
screen_buf[doFire_idx - FIRE_W] = 0;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
spread_rnd_idx = rand.intRangeAtMost(u8, 0, 3);
|
spread_rnd_idx = rand.intRangeAtMost(u8, 0, 3);
|
||||||
if (doFire_idx>=(spread_rnd_idx+1)) {
|
if (doFire_idx >= (spread_rnd_idx + 1)) {
|
||||||
spread_dst=doFire_idx-spread_rnd_idx+1;
|
spread_dst = doFire_idx - spread_rnd_idx + 1;
|
||||||
}
|
}
|
||||||
if (( spread_dst>=FIRE_W ) and (spread_px > (spread_rnd_idx & 1))) {
|
if ((spread_dst >= FIRE_W) and (spread_px > (spread_rnd_idx & 1))) {
|
||||||
screen_buf[spread_dst-FIRE_W]=spread_px - (spread_rnd_idx & 1);
|
screen_buf[spread_dst - FIRE_W] = spread_px - (spread_rnd_idx & 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -623,33 +635,33 @@ pub fn showDoomFire() void {
|
||||||
drawBuf(init_frame);
|
drawBuf(init_frame);
|
||||||
|
|
||||||
// for each row
|
// for each row
|
||||||
frame_y=0;
|
frame_y = 0;
|
||||||
while (frame_y<FIRE_H) {
|
while (frame_y < FIRE_H) {
|
||||||
defer frame_y+=2; // 'paint' two rows at a time because of half height char
|
defer frame_y += 2; // 'paint' two rows at a time because of half height char
|
||||||
|
|
||||||
// for each col
|
// for each col
|
||||||
frame_x=0;
|
frame_x = 0;
|
||||||
while (frame_x<FIRE_W) {
|
while (frame_x < FIRE_W) {
|
||||||
defer frame_x+=1;
|
defer frame_x += 1;
|
||||||
|
|
||||||
//each character rendered is actually to rows of 'pixels'
|
//each character rendered is actually to rows of 'pixels'
|
||||||
// - "hi" (current px row => fg char)
|
// - "hi" (current px row => fg char)
|
||||||
// - "low" (next row => bg color)
|
// - "low" (next row => bg color)
|
||||||
px_hi=screen_buf[frame_y*FIRE_W+frame_x];
|
px_hi = screen_buf[frame_y * FIRE_W + frame_x];
|
||||||
px_lo=screen_buf[(frame_y+1)*FIRE_W+frame_x];
|
px_lo = screen_buf[(frame_y + 1) * FIRE_W + frame_x];
|
||||||
|
|
||||||
// only *update* color if prior color is actually diff
|
// only *update* color if prior color is actually diff
|
||||||
if (px_lo!=px_prev_lo) {
|
if (px_lo != px_prev_lo) {
|
||||||
drawBuf(bg[fire_palette[px_lo]]);
|
drawBuf(bg[fire_palette[px_lo]]);
|
||||||
}
|
}
|
||||||
if (px_hi!=px_prev_hi) {
|
if (px_hi != px_prev_hi) {
|
||||||
drawBuf(fg[fire_palette[px_hi]]);
|
drawBuf(fg[fire_palette[px_hi]]);
|
||||||
}
|
}
|
||||||
drawBuf(px);
|
drawBuf(px);
|
||||||
|
|
||||||
//cache current colors
|
//cache current colors
|
||||||
px_prev_hi=px_hi;
|
px_prev_hi = px_hi;
|
||||||
px_prev_lo=px_lo;
|
px_prev_lo = px_lo;
|
||||||
}
|
}
|
||||||
drawBuf(nl); //is this needed?
|
drawBuf(nl); //is this needed?
|
||||||
}
|
}
|
||||||
|
@ -669,5 +681,4 @@ pub fn main() anyerror!void {
|
||||||
checkTermSz();
|
checkTermSz();
|
||||||
showTermCap();
|
showTermCap();
|
||||||
showDoomFire();
|
showDoomFire();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue