Skip to content

Corg-Labs/chaos

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Chaos Game — Sierpinski Triangle in C

The Sierpinski triangle drawn via the chaos game — an iterated function system where a point repeatedly jumps halfway toward a randomly chosen triangle vertex, gradually filling in a fractal. Each vertex colours its offspring differently, revealing the three self-similar sub-triangles.

Rendered as coloured blocks via SDL2.


Features

  • Sierpinski triangle via the chaos game iterated function system
  • 200 points per frame at ~40 fps
  • Per-vertex colour coding: coral, cyan, gold
  • True 24‑bit color rendering via SDL2 framebuffer
  • 960 × 480 window (80 × 40 grid, 12 px per cell)
  • Live point counter in window title
  • Accumulating canvas — grid persists across frames
  • Keyboard and Ctrl-C quit handling
  • Written entirely in C

How It Works

Three fixed vertices define a triangle. A moving point starts at the centre, then repeatedly picks a random vertex and moves halfway toward it, marking each position on the grid. After a few thousand iterations the Sierpinski fractal emerges from the seemingly random motion. Each vertex's branch is drawn in a distinct colour, revealing the three-way self-similarity.


Tutorial / Fractal Algorithm

1. The Grid

The fractal is drawn onto an 80 × 40 grid of unsigned bytes. 0 means empty; 1, 2, or 3 records which vertex last claimed that cell:

#define W  80
#define H  40

unsigned char grid[H][W];
memset(grid, 0, sizeof(grid));

Each frame, the grid is rendered as coloured 12 × 12 pixel blocks in an SDL2 surface.


2. The Three Vertices

Three corners span the triangle in screen coordinates:

int vx[3] = {0, W - 1, W / 2};
int vy[3] = {H - 1, H - 1, 0};
Vertex Position Colour
0 Bottom-left Coral (255, 80, 80)
1 Bottom-right Cyan (80, 220, 255)
2 Top-centre Gold (255, 220, 80)

3. The Chaos Game

The core algorithm is an iterated function system (IFS):

double px = W / 2.0, py = H / 2.0;    /* starting point */

for (int k = 0; k < 200; k++) {
    int i = rand() % 3;                /* pick a random vertex */
    px = (px + vx[i]) / 2.0;          /* jump halfway */
    py = (py + vy[i]) / 2.0;
    int ix = (int)px, iy = (int)py;
    if (ix >= 0 && ix < W && iy >= 0 && iy < H)
        grid[iy][ix] = 1 + i;          /* mark with vertex colour */
}

The key insight: repeatedly jumping halfway toward a randomly chosen vertex always converges to the Sierpinski triangle, regardless of the starting position. The first few hundred points may fall outside the fractal, but they are quickly buried by correct ones.


4. Per-Vertex Colour Coding

Each cell stores 1 + vertex_index (1, 2, or 3) so the renderer can colour it by origin vertex:

Uint32 col_v[3] = {
    SDL_MapRGB(fmt, 255, 80,  80),   /* coral */
    SDL_MapRGB(fmt, 80,  220, 255),  /* cyan  */
    SDL_MapRGB(fmt, 255, 220, 80),   /* gold  */
};

for (each cell) {
    Uint32 color = grid[y][x] ? col_v[grid[y][x] - 1] : col_bg;
    /* fill CELL × CELL block */
}

The three colours make the three-way recursive subdivision immediately visible: each vertex's "territory" forms a distinct third of the fractal.


5. Grid Rendering

Each cell is drawn as a 12 × 12 pixel block:

for (int py = 0; py < CELL; py++)
    for (int px = 0; px < CELL; px++)
        pixels[(y * CELL + py) * pitch + (x * CELL + px)] = color;

Empty cells render as a near-black navy background.


6. Batching and Frame Timing

200 points are computed per frame. The grid persists across frames — once a cell is marked it stays marked:

for (int k = 0; k < 200 && running; k++) {
    /* ... jump and mark ... */
}

The window title updates each frame with the cumulative count:

snprintf(title, sizeof title, "Chaos Game — %ld points", step);
SDL_SetWindowTitle(win, title);

A 40 fps cap keeps CPU usage low:

Uint32 elapsed = SDL_GetTicks() - frame_start;
if (elapsed < 25) SDL_Delay(25 - elapsed);

Build

git clone <this-repo>
cd chaos
make

Or manually:

gcc chaos.c -o chaos $(sdl2-config --cflags --libs)

Dependencies: SDL2 and a C compiler (gcc/clang).

Install SDL2 via Homebrew:

brew install sdl2

Or apt:

sudo apt install libsdl2-dev

Run

./chaos

Controls:

  • ESC or Q — quit
  • Ctrl-C — quit (fallback)

Customizing

Edit constants at the top of chaos.c:

  • W, H — grid resolution
  • CELL — pixel size per cell
  • Vertex positions vx, vy — change the triangle shape
  • Vertex colours col_v[] — any RGB triple
  • Batch size (200) — points per frame

Concepts Practiced

  • Iterated function systems (IFS) for fractal generation
  • Chaos game algorithm (random midpoint displacement)
  • Sierpinski triangle — three-way recursive self-similarity
  • Per-vertex colour coding to reveal sub-structure
  • Accumulating grid buffer (write-once, render-each-frame)
  • SDL2 surface/pixel-buffer graphics
  • Cell-based block rendering
  • Real-time animation with frame-rate capping

Dependencies

  • SDL.h — window management and pixel buffer
  • stdio.hsnprintf, stderr diagnostics
  • stdlib.hrand, srand, NULL
  • string.hmemset
  • time.htime for RNG seed
  • signal.hSIGINT handler

About

► Sierpinski triangle drawn with the chaos game, in C.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors