Skip to content
intriXlabsPublic

About

A zero-dependency C++ framework for programmable procedural tiles in the terminal. Create dynamic tile simulations from mathematical patterns, customize each tile's characters and colors, and render them directly to ANSI-compatible terminals.

Resources

Stars

7 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

7 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

simulaii

Version C++ Platform Dependencies Tiles Patterns License

One tile. Thirty lives. Unlimited layouts.

A zero-dependency C++ tile framework for building animated terminal scenes β€” where every tile is a procedurally rendered rectangle of motion.


Quick Demos:

All Together

Normal 1-10

Premiums 11-20

3D & 4D 21-30


Important Note

simulaii renders to POSIX terminals (Linux, macOS, BSD, WSL) and relies on ANSI escape codes and 24-bit true-color support to position the cursor and color each cell.

Zero-Dependency by Design

There is no terminal-size detection, no window API, no ncurses, no scene graph library. You create tiles, give each one a rectangle, a color, and a pattern β€” and the framework handles the rest.

That means:

  • The library contains no platform-specific code
  • It compiles anywhere a C++11 compiler exists
  • The same source can drive a Linux TTY, an Android terminal, or a Windows console with ANSI enabled β€” as long as your terminal supports 24-bit color and cursor positioning

simulaii handles the tiles. Where the terminal lives is up to you.


πŸ“– Table of Contents


🌟 Overview

simulaii is a tile-based animation framework for the terminal. Every tile is a rectangle. Every rectangle is alive. You place tiles wherever you want on the grid, give each one a color and a pattern, and advance them together to compose a moving scene.

The name is a union of "simulate" and "ASCII". Simulation, because every tile's contents are generated from sine waves, distance fields, and rotation matrices β€” not from a lookup table. ASCII, because the output is still just characters on a grid.

Why Tiles?

A terminal is a grid of characters. Most of the time, that grid is static β€” text goes in, text comes out. But the grid can also be a canvas, and the canvas can be partitioned. Each partition is a tile. Each tile runs its own simulation. Together, they form a scene.

That's the whole idea.

  • A tile is a rectangle with a personality. Position, size, color, pattern β€” nothing else.
  • A scene is a collection of tiles. Lay them out however you want. They don't know about each other.
  • A frame is one tick per tile. Call nextFrame() on each, in any order, at any rate.
  • A pattern is a tile's mind. Thirty of them ship in the box. A thirty-first is one function away.

simulaii doesn't try to own your terminal. It gives you movable, animatable rectangles and lets you arrange them.


✨ Features

🧱 Tile Primitives

  • Positioned Rectangles β€” Every tile lives at (row, col) with an explicit width and height
  • Independent State β€” Each tile has its own color, pattern, and internal clock
  • Unlimited Tiles β€” Instantiate as many as your terminal can hold
  • No Layout Engine β€” You decide where each tile goes; the framework just draws it

🎨 Rendering

  • 24-bit True Color β€” Full RGB via #RRGGBB hex strings, per tile
  • Four Block Characters β€” β–‘ β–’ β–“ β–ˆ as the default tile palette
  • Replaceable Glyphs β€” Swap the four characters on any tile, at any time
  • Cell-by-Cell Drawing β€” Every frame writes directly to the terminal grid

πŸŒ€ Animation

  • 30 Built-in Tile Patterns β€” Ten wave-based, ten radial/flow, ten 3D/4D wireframes
  • Time-Based Motion β€” Each tile carries its own clock; no frame-counter math required
  • Deterministic β€” The same tick on the same tile always produces the same image
  • Stateless Between Frames β€” Patterns store no accumulation; the math is self-contained

🧩 Developer-Friendly

  • One Class = One Tile β€” Construct it, style it, tick it
  • Bounds Checked β€” Invalid constructor arguments throw early, not mid-render
  • Zero Setup β€” No init, no shutdown, no global state
  • Style Anytime β€” Color and glyphs can change between frames

🧱 The Tile Model

simulaii is built on a single abstraction: the animated tile.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                                  β”‚
β”‚                     A TILE                       β”‚
β”‚                                                  β”‚
β”‚   position  β†’  (row, col)                        β”‚
β”‚   size      β†’  (width, height)                   β”‚
β”‚   style     β†’  #RRGGBB  +  4 glyphs              β”‚
β”‚   mind      β†’  pattern number (1–30)             β”‚
β”‚   clock     β†’  advanced by nextFrame()           β”‚
β”‚                                                  β”‚
β”‚   ─────────────────────────────────────────      β”‚
β”‚                                                  β”‚
β”‚   On every tick, the tile:                       β”‚
β”‚     1. evaluates its pattern for each cell       β”‚
β”‚     2. maps the value to one of its 4 glyphs     β”‚
β”‚     3. writes that glyph at the correct          β”‚
β”‚        cursor position in the tile's color       β”‚
β”‚                                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

A scene is what you get when several tiles share the screen:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  tile A  (#FF0066, pattern 6)   β”‚  tile B  (#00FFAA, p 24) β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                             β”‚
β”‚                  tile C  (#FFFFFF, pattern 30)              β”‚
β”‚                                                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  tile D  (#FFAA00, pattern 3)                               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

None of the tiles know the others exist. Composition is your job β€” the framework just gives you rectangles that move.


🎭 The 30 Tile Patterns

Every tile picks one pattern from a menu of thirty. A pattern defines what the tile looks like as time advances. Three families, ten patterns each.

β–Έ Patterns 1–10 β€” Wave Tiles

Pure sine-based motion. Diagonals, grids, rings, plasmas, vortices.

# Name Description
1 Diagonal Sine A calm diagonal wave drifting across the tile
2 Cross Grid Horizontal and vertical waves crossing into a shifting grid
3 Concentric Rings Rings pulsing outward from the tile's center
4 Double Slit Two wave sources interfering, physics-lab style
5 Rotating Spiral A spiral arm orbiting the tile's center
6 Classic Plasma Four waves blended into liquid motion
7 Breathing Vortex A spiral whose tightness expands and contracts
8 MoirΓ© Stacked waves producing an optical-illusion pattern
9 Flow Field Organic, watery turbulence from stacked trig
10 Full Hypnotic Spiral + radial + diagonals + breath, combined

Feels like: still water, then wind, then something alive underneath.

β–Έ Patterns 11–20 β€” Premium Wave Tiles

The same family, but with extra layers β€” rotation, moving sources, dual harmonics.

# Name Description
11 Flowing Diagonal Two crossed diagonals for a softer, water-like flow
12 Rotating Cross Cross waves that slowly rotate about the center
13 Moving Ripples A ripple source that wanders around the tile
14 Drifting Double Slit Double-slit interference with sources in motion
15 Galaxy Spiral Slow-rotating spiral arms, galactic feel
16 Plasma Fire Four-wave plasma tuned for warmer motion
17 Breathing Vortex II Vortex with a stronger breathing rhythm
18 MoirΓ© II Stacked waves shifting at a different rate
19 Flow Field II Water-surface turbulence with different constants
20 Full Hypnotic II The peak combo β€” every trick in one frame

Feels like: the wave tiles, but with more depth β€” the same water, deeper.

β–Έ Patterns 21–30 β€” 3D & 4D Geometry Tiles

Rotating wireframes projected into 2D, then drawn as ASCII.

# Name Description
21 Rotating Cube A classic wireframe cube tumbling on two axes
22 Rotating Octahedron Eight triangular faces, wireframe-only
23 Rotating Torus A donut of points rotating through 3D
24 Rotating Sphere Lat/long grid projected onto a rotating sphere
25 Rotating Pyramid A square pyramid spinning on its base
26 Double Helix Two intertwined strands, DNA-style
27 Rotating Cylinder A stack of rings forming a cylinder
28 Dodecahedron Golden-ratio vertices, projected and drawn
29 MΓΆbius Strip The classic one-sided surface, rotating
30 Tesseract A 4D hypercube projected down to 2D

Feels like: geometry homework, if geometry homework was hypnotic.

simulaii tile(2, 4, 60, 20, "#00FFAA", 30);  // tesseract tile, mint green

πŸ— Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       Scene Layer                           β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚   β”‚   tile A      β”‚  β”‚   tile B      β”‚  β”‚   tile C      β”‚   β”‚
β”‚   β”‚  (its own     β”‚  β”‚  (its own     β”‚  β”‚  (its own     β”‚   β”‚
β”‚   β”‚   rect,       β”‚  β”‚   rect,       β”‚  β”‚   rect,       β”‚   β”‚
β”‚   β”‚   color,      β”‚  β”‚   color,      β”‚  β”‚   color,      β”‚   β”‚
β”‚   β”‚   pattern,    β”‚  β”‚   pattern,    β”‚  β”‚   pattern,    β”‚   β”‚
β”‚   β”‚   clock)      β”‚  β”‚   clock)      β”‚  β”‚   clock)      β”‚   β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                             β”‚
β”‚       You compose this. The framework doesn't.              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Tile Internals                          β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚   β”‚  position  β€’  size  β€’  color  β€’  glyphs  β€’  clock  β”‚    β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   Pattern Dispatcher                        β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚   β”‚   switch(pattern) β†’ drawBoxPatternN()              β”‚    β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   Per-Cell Math Layer                       β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚   β”‚   sin / cos / atan2 / sqrt  β†’  value in [0, 1]     β”‚    β”‚
β”‚   β”‚   value  β†’  index in [0, 3]  β†’  block character    β”‚    β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Terminal Layer                          β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚   β”‚   Cursor positioning  β€’  Foreground color          β”‚    β”‚
β”‚   β”‚   Row-by-row write    β€’  Reset after frame         β”‚    β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            ↓
                    Terminal Display

Each tile draws directly to the terminal, into its own rectangle. There's no framebuffer, no scene graph, no diffing β€” just characters landing in place, tile by tile, every frame.

Because each tile owns its cursor coordinates, tiles can be laid out side-by-side, stacked, or overlapped. The framework doesn't enforce a layout β€” it just provides the primitive.


πŸš€ Quick Start

Prerequisites

  • C++11 or higher compiler
  • POSIX terminal β€” Linux, macOS, BSD, WSL
  • 24-bit true-color support β€” Most modern terminals handle this
  • ANSI escape code support β€” For cursor positioning

Installation

simulaii is a single C++ class. Drop it into your project.

# Clone or copy simulaii.cpp into your project

# Compile with optimizations
g++ -O3 -std=c++11 your_scene.cpp -o your_scene

# Run
./your_scene

Minimal Example β€” One Tile

#include "simulaii.cpp"
#include <thread>
#include <chrono>

int main() {
    //              row  col  width  height  color      pattern
    simulaii tile(  2,   4,   60,    20,    "#00FFAA", 6);

    while (true) {
        tile.nextFrame();
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }

    return 0;
}

Six lines. One tile. One loop.


🧩 Composing a Scene

A scene is just more than one tile. Each tile is independent β€” different color, different pattern, different position β€” but they share the same loop.

Example: Four-Tile Dashboard

#include "simulaii.cpp"
#include <thread>
#include <chrono>

int main() {
    //          row  col  w    h   color      pattern
    simulaii header( 0,   0,  80,   3, "#FF0066",  6);   // plasma header
    simulaii side(   3,   0,  20,  20, "#00FFAA", 24);   // rotating sphere
    simulaii main(   3,  20,  60,  20, "#FFFFFF", 30);   // tesseract
    simulaii footer(23,   0,  80,   2, "#FFAA00",  3);   // pulsing rings

    while (true) {
        header.nextFrame();
        side.nextFrame();
        main.nextFrame();
        footer.nextFrame();

        std::this_thread::sleep_for(std::chrono::milliseconds(50));
    }

    return 0;
}

Four tiles. One screen. A live scene.

Example: Restyling a Tile Mid-Run

simulaii tile(2, 4, 60, 20, "#FF0066", 10);

tile.nextFrame();

tile.setColor("#00FFAA");                    // new color, same pattern

std::string newGlyphs[4] = {"+","-","=","#"};
tile.changePrimitiveCharacters(newGlyphs);   // new glyph set

tile.nextFrame();

Tiles are stylable at runtime. Color and glyphs are not fixed.

Example: A Tile Grid

const int TILE_W = 20, TILE_H = 10;
int p = 1;
for (int r = 0; r < 3; ++r)
    for (int c = 0; c < 4; ++c)
        tiles.emplace_back(r * TILE_H, c * TILE_W, TILE_W, TILE_H,
                           "#FFFFFF", p++);

That's a 12-tile grid, one pattern per tile. Compose whatever you want.


🎯 Use Cases

1. Terminal Dashboards

A grid of tiles, each showing a different animated indicator. Plasma for "running," rings for "waiting," a sphere for "synced." The tile model maps directly onto a dashboard layout.

2. HUDs & Status Bars

A header tile with a slow plasma wave. A footer tile pulsing in your brand color. A corner tile showing a rotating cube while a build runs.

3. Boot Screens & Installers

Multiple tiles composing a layout while your installer copies files. Header tesseract, side dodecahedron, main progress box, footer ripples.

4. Multi-Panel TUI Layouts

You already use a TUI library for input and layout β€” simulaii becomes the content of every panel. Tiles fill the rectangles your layout engine creates.

5. Stream Overlays

A tile-based overlay in OBS. Compose your scene, style each tile to match your brand, run it. The tiles don't know they're on stream.

6. Terminal Art & Demos

A full-screen grid of thirty tiles, one per pattern, all advancing together. A showcase scene.

7. Learning Tool

Every pattern is a pure function of (i, j, t) inside a fixed rectangle. Read the source, change a constant, see what happens. A tile is the smallest unit of graphics you can play with.


🌈 Why simulaii

Most terminal animation libraries either go tiny (a spinner) or enormous (a full TUI framework with a scene graph, layout engine, and event loop). simulaii sits in the middle.

It gives you one primitive β€” the animated tile β€” and lets you build the rest. Layout is your job. Composition is your job. Timing across tiles is your job. But everything inside a tile is done for you, thirty times over.

It doesn't want to own your terminal. It wants to hand you rectangles that move, and then get out of the way.

If you're building anything in a terminal that has more than one region β€” a dashboard, a status bar, a live footer, a boot screen β€” you already have tiles. simulaii is what fills them.


βš–οΈ Comparison

simulaii Manual ASCII loops TUI Frameworks Graphics Libraries
Dependencies None None Several Many
Setup One class per tile Custom per region Framework to learn Build system, drivers
Unit of Work Animated tile Custom Widget Framebuffer
Tiles in a Scene Unlimited Manual Widget instances N/A
Tile Patterns Included 30 0 ~0 ∞
True Color Yes Manual Varies N/A
Runs in Terminal Yes Yes Yes No
Learning Curve Minutes Hours Hours to days Days to weeks
Scope Animated tiles Anything Full-screen UI Full-screen pixels

simulaii doesn't replace your TUI library. It becomes the tile primitive inside it β€” one class per region, thirty ways to make each region move.


🧬 Design Philosophy

simulaii is deliberately narrow.

  • It animates one rectangle.
  • It uses four characters.
  • It exposes one method for advancing time.
  • It ships with thirty patterns, but adding a thirty-first is a single function.

Every tile is a self-contained unit. It doesn't know about other tiles. It doesn't know the terminal size. It doesn't know the frame rate. It just knows: "I am a rectangle at (row, col), this big, this color, running this pattern, and I advance one tick when told."

That minimalism is the point. A tile is the smallest animated thing that can exist on a terminal. Compose tiles; get scenes.

Every pattern is a pure function of position and time. No frame buffers, no noise textures, no asset files. The math is the animation.

You're not meant to leave it alone. Change the constants. Rewrite a pattern. Replace the block characters with emoji. Lay tiles out however you want. The source is short enough to read in one sitting, and the tile primitive is simple enough to fork in an afternoon.

It's a framework for people who want to see something move β€” and who want to compose the motion themselves.


πŸ“š API Reference

Constructor

simulaii(int row, int col, int width, int height,
         std::string color, int patternNumber = 1);

Creates a tile and immediately renders the first frame of the chosen pattern.

  • row, col β€” 0-indexed top-left corner of the tile
  • width, height β€” size of the tile in cells
  • color β€” hex color string, "#RRGGBB"
  • patternNumber β€” 1 to 30

Throws std::invalid_argument on bad bounds or an out-of-range pattern.

nextFrame()

int nextFrame();

Advances this tile's internal clock by one tick and redraws the entire tile. Other tiles are unaffected β€” you decide the tick order in your scene loop.

Returns 0 on success.

setColor()

int setColor(std::string hexColor);

Changes the tile's foreground color. Takes effect on the next frame.

Throws std::invalid_argument if the string is not #RRGGBB.

removeColor()

int removeColor();

Resets the tile's color to white (#FFFFFF).

changePrimitiveCharacters()

int changePrimitiveCharacters(std::string newChars[4]);

Replaces the four glyphs used to render the tile. Only the first character of each string is used.

Default glyphs: β–‘ β–’ β–“ β–ˆ


πŸ“„ License

Licensed under the apache 2.0 License. See LICENSE for details.


One tile. Thirty lives. Unlimited layouts.

"Every tile is a rectangle. Every rectangle is alive. The scene is yours to compose."

⬆ Back to Top

About

A zero-dependency C++ framework for programmable procedural tiles in the terminal. Create dynamic tile simulations from mathematical patterns, customize each tile's characters and colors, and render them directly to ANSI-compatible terminals.

Resources

Stars

7 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages