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();
|
||||||
|
|
99
src/main.zig
99
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
|
||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
|
@ -60,7 +65,9 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,8 +84,8 @@ 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 };
|
||||||
|
@ -142,14 +149,16 @@ 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) { return TermSz{ .height = winsz.ws_row, .width = winsz.ws_col }; }
|
if (rv == 0) {
|
||||||
else {return std.os.unexpectedErrno(err);}
|
return TermSz{ .height = winsz.ws_row, .width = winsz.ws_col };
|
||||||
|
} else {
|
||||||
|
return std.os.unexpectedErrno(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initTermSize() !void {
|
pub fn initTermSize() !void {
|
||||||
|
@ -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.
|
||||||
///
|
///
|
||||||
|
@ -204,22 +212,32 @@ pub fn checkTermSz() void {
|
||||||
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,7 +262,6 @@ 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 });
|
||||||
|
@ -263,7 +280,9 @@ pub fn showStdColors() void {
|
||||||
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(fg[0]);
|
||||||
|
}
|
||||||
emit_fmt("{u} {d:2} ", .{ sep, color_idx });
|
emit_fmt("{u} {d:2} ", .{ sep, color_idx });
|
||||||
}
|
}
|
||||||
emit(nl);
|
emit(nl);
|
||||||
|
@ -273,9 +292,10 @@ pub fn showStdColors() void {
|
||||||
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(fg[0]);
|
||||||
|
}
|
||||||
emit_fmt("{u} {d:2} ", .{ sep, color_idx });
|
emit_fmt("{u} {d:2} ", .{ sep, color_idx });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(nl);
|
emit(nl);
|
||||||
|
@ -307,8 +327,7 @@ pub fn show216Colors() void {
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,15 +378,7 @@ 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",
|
|
||||||
" 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
|
const txt_len: u8 = txt.len / 2; // print two rows at a time
|
||||||
|
|
||||||
//fade txt in and out
|
//fade txt in and out
|
||||||
|
@ -405,7 +416,6 @@ 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) {
|
||||||
|
@ -461,7 +471,6 @@ 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;
|
||||||
|
@ -501,10 +510,13 @@ pub fn paintBuf() void {
|
||||||
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 {
|
||||||
|
if (bs_len < bs_sz_min) {
|
||||||
|
bs_sz_min = bs_len;
|
||||||
|
}
|
||||||
|
if (bs_len > bs_sz_max) {
|
||||||
|
bs_sz_max = bs_len;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if( bs_len < bs_sz_min) { 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;
|
bs_sz_avg = bs_sz_avg * (bs_frame_tic - 1) / bs_frame_tic + bs_len / bs_frame_tic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,8 +528,9 @@ pub fn paintBuf() void {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -605,8 +618,7 @@ pub fn showDoomFire() void {
|
||||||
//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;
|
||||||
|
@ -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