p-e-w / ternimal
- понедельник, 6 ноября 2017 г. в 03:13:26
Simulate a lifeform in the terminal
Ternimal (note the spelling) is a program that draws an animated lifeform in the terminal using Unicode block symbols. It works in most terminal emulators and with most monospaced fonts.
From a practical perspective, the program is not very useful. It does, however, contain quite a bit of cool technology and math:
Ternimal is also an exercise in minimalism and restraint. Written in just 1000 lines of Rust, it has no dependencies and consumes very few resources: 400 kB on disk, 3 MB of RAM and 4 % of a single CPU core with the default parameters. It implements its own linear algebra operations from scratch, as well as basic command line parsing and a simple random number generator.
Ternimal has no dependencies apart from the Rust Standard Library, and does not require Cargo for building. Only rustc
(>= 1.20) must be installed, at which point Ternimal can be built with:
git clone https://github.com/p-e-w/ternimal.git
cd ternimal
rustc -O ternimal.rs
Fundamentally, Ternimal does nothing more than color the distance field from a segmented spine moving along a meandering path. There are many parameters controlling this process, however, nearly all of which can be manipulated through the command line.
This makes the system very flexible. The following are just a few examples of what is possible:
./ternimal length=100 segments=50 thickness=1,4,1,0 radius=6,12 gradient=0:#666600,0.5:#00ff00,1:#003300
Sine waves can be used to generate quite organic-looking shapes. In this case, a single half-wave forms the body of a snake.
./ternimal length=200 segments=50 thickness=0,4,19,0
Ternimal only renders a single model. However, thickness variations can give the appearance of multiple disconnected entities moving in a coordinated fashion.
./ternimal length=20 thickness=70,15,0,5 padding=10 radius=5 gradient=0.03:#ffff00,0.15:#0000ff,0.3:#ff0000,0.5:#00ff00
The thickness function includes a time parameter. This makes it possible to define shape animations. Arbitrarily many Fourier series terms can be specified, enabling very complex animations.
./ternimal speed=10 length=100 segments=5 thickness=13 gradient=0.5:#000000,0.8:#ffffff,1:#000000
Creatively combining low segment counts, wide distance fields, and appropriately chosen gradients can produce output that seemingly goes beyond what is possible with spine-based rendering alone.
Most likely because your terminal does not support 24-bit RGB color escape sequences. This in turn probably means that you are using macOS' default Terminal.app, which is the only major terminal emulator still missing that feature.
You have two options:
true_color=false
to fall back to a 256-color palette, which is supported by practically every terminal emulator (but doesn't look as nice).Either because your font's block characters do not completely fill the character cell, or because your terminal has line spacing greater than zero.
Ternimal works best with fonts that have a character aspect ratio as close to 2:1 as possible. The font in the screencasts is the wonderful Iosevka.
The Linux console does not support Unicode fonts. It does, however, appear to recognize the Unicode encoding, and attempts to translate certain Unicode code points to code points in its internal encoding, which includes the block symbols required by Ternimal.
There appears to be a bug in this conversion, though. The UPPER HALF BLOCK character is translated correctly, but the LOWER HALF BLOCK is not, resulting in a striped pattern.
No idea.
I'd love to know, though, so if you get it to build and run in some terminal emulator, I would appreciate if you could file an issue with a brief description and if possible some screenshots/screencasts.
Like this:
Contributors are always welcome. However, please file an issue describing what you intend to add before opening a pull request, especially for new features! I have a clear vision of what I want (and do not want) Ternimal to be, so discussing potential additions might help you avoid duplication and wasted work.
By contributing, you agree to release your changes under the same license as the rest of the project (see below).
Copyright © 2017 Philipp Emanuel Weidmann (pew@worldwidemann.com)
Released under the terms of the GNU General Public License, version 3