Agent skill

generative-art-algorithms

Create algorithmic and generative art using mathematical patterns, noise functions, particle systems, and procedural generation. Covers flow fields, L-systems, fractals, and creative coding foundations. Triggers on generative art, algorithmic art, creative coding, procedural generation, or mathematical visualization requests.

Stars 163
Forks 31

Install this agent skill to your Project

npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/generative-art-algorithms

SKILL.md

Generative Art Algorithms

Create art through code, mathematics, and emergence.

Core Philosophy

Generative Art Principles

  1. Rules create emergence - Simple rules yield complex results
  2. Controlled randomness - Seeded random for reproducibility
  3. Parameter exploration - Same algorithm, infinite variations
  4. Happy accidents - Bugs as features

The Creative Coding Loop

Idea → Algorithm → Parameters → Render → Evaluate → Iterate
   ↑                                                   │
   └───────────────────────────────────────────────────┘

Noise Functions

Perlin/Simplex Noise

Smooth, continuous random values perfect for organic motion.

javascript
// p5.js example
function draw() {
  for (let x = 0; x < width; x++) {
    for (let y = 0; y < height; y++) {
      let n = noise(x * 0.01, y * 0.01, frameCount * 0.01);
      stroke(n * 255);
      point(x, y);
    }
  }
}

Noise Parameters

Parameter Effect
Scale (frequency) Zoom level of noise (smaller = more detail)
Octaves Layers of detail
Amplitude Height of values
Time offset Animate through noise space

Noise Applications

  • Terrain generation
  • Texture synthesis
  • Organic movement
  • Flow fields
  • Cloud/smoke effects

Flow Fields

Basic Flow Field

javascript
// Generate angle at each grid point from noise
function setup() {
  createCanvas(800, 800);
  
  let resolution = 20;
  let cols = width / resolution;
  let rows = height / resolution;
  
  for (let y = 0; y < rows; y++) {
    for (let x = 0; x < cols; x++) {
      let angle = noise(x * 0.1, y * 0.1) * TWO_PI * 2;
      
      // Draw vector
      push();
      translate(x * resolution, y * resolution);
      rotate(angle);
      stroke(0);
      line(0, 0, resolution * 0.8, 0);
      pop();
    }
  }
}

Particles in Flow Field

javascript
class Particle {
  constructor() {
    this.pos = createVector(random(width), random(height));
    this.vel = createVector(0, 0);
    this.acc = createVector(0, 0);
    this.maxSpeed = 2;
    this.prevPos = this.pos.copy();
  }
  
  follow(flowField, resolution) {
    let x = floor(this.pos.x / resolution);
    let y = floor(this.pos.y / resolution);
    let index = x + y * floor(width / resolution);
    let force = flowField[index];
    this.applyForce(force);
  }
  
  applyForce(force) {
    this.acc.add(force);
  }
  
  update() {
    this.vel.add(this.acc);
    this.vel.limit(this.maxSpeed);
    this.prevPos = this.pos.copy();
    this.pos.add(this.vel);
    this.acc.mult(0);
  }
  
  edges() {
    if (this.pos.x > width) { this.pos.x = 0; this.prevPos.x = 0; }
    if (this.pos.x < 0) { this.pos.x = width; this.prevPos.x = width; }
    if (this.pos.y > width) { this.pos.y = 0; this.prevPos.y = 0; }
    if (this.pos.y < 0) { this.pos.y = height; this.prevPos.y = height; }
  }
  
  show() {
    stroke(0, 10);
    strokeWeight(1);
    line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
  }
}

L-Systems

Grammar Structure

Axiom: Starting string
Rules: Replacement rules
Angle: Turning angle
Iterations: Recursion depth

Classic L-Systems

Fractal Tree:

Axiom: F
Rules: F → FF+[+F-F-F]-[-F+F+F]
Angle: 25°

Koch Snowflake:

Axiom: F
Rules: F → F+F--F+F
Angle: 60°

Sierpinski Triangle:

Axiom: F-G-G
Rules: F → F-G+F+G-F, G → GG
Angle: 120°

L-System Rendering

javascript
// Interpret string as drawing commands
function render(sentence) {
  for (let char of sentence) {
    switch(char) {
      case 'F':
        line(0, 0, 0, -len);
        translate(0, -len);
        break;
      case '+':
        rotate(angle);
        break;
      case '-':
        rotate(-angle);
        break;
      case '[':
        push();
        break;
      case ']':
        pop();
        break;
    }
  }
}

Fractals

Mandelbrot Set

javascript
function mandelbrot(x, y, maxIter) {
  let real = x;
  let imag = y;
  
  for (let i = 0; i < maxIter; i++) {
    let tempReal = real * real - imag * imag + x;
    imag = 2 * real * imag + y;
    real = tempReal;
    
    if (real * real + imag * imag > 4) {
      return i;
    }
  }
  return maxIter;
}

Julia Set

Same iteration, different starting point:

javascript
function julia(x, y, cx, cy, maxIter) {
  let real = x;
  let imag = y;
  
  for (let i = 0; i < maxIter; i++) {
    let tempReal = real * real - imag * imag + cx;
    imag = 2 * real * imag + cy;
    real = tempReal;
    
    if (real * real + imag * imag > 4) {
      return i;
    }
  }
  return maxIter;
}

Recursive Subdivision

javascript
function subdivide(x, y, w, h, depth) {
  if (depth === 0 || w < 2 || h < 2) {
    rect(x, y, w, h);
    return;
  }
  
  let splitH = random() > 0.5;
  
  if (splitH) {
    let split = random(0.3, 0.7) * w;
    subdivide(x, y, split, h, depth - 1);
    subdivide(x + split, y, w - split, h, depth - 1);
  } else {
    let split = random(0.3, 0.7) * h;
    subdivide(x, y, w, split, depth - 1);
    subdivide(x, y + split, w, h - split, depth - 1);
  }
}

Particle Systems

Basic Particle

javascript
class Particle {
  constructor(x, y) {
    this.pos = createVector(x, y);
    this.vel = p5.Vector.random2D().mult(random(1, 3));
    this.acc = createVector(0, 0);
    this.lifespan = 255;
    this.size = random(5, 15);
  }
  
  applyForce(force) {
    this.acc.add(force);
  }
  
  update() {
    this.vel.add(this.acc);
    this.pos.add(this.vel);
    this.acc.mult(0);
    this.lifespan -= 2;
  }
  
  isDead() {
    return this.lifespan <= 0;
  }
  
  show() {
    noStroke();
    fill(255, this.lifespan);
    ellipse(this.pos.x, this.pos.y, this.size);
  }
}

Forces

javascript
// Gravity
let gravity = createVector(0, 0.1);
particle.applyForce(gravity);

// Attraction to point
function attract(target, particle, strength) {
  let force = p5.Vector.sub(target, particle.pos);
  let distance = constrain(force.mag(), 5, 25);
  force.normalize();
  let magnitude = strength / (distance * distance);
  force.mult(magnitude);
  return force;
}

// Repulsion
function repel(target, particle, strength) {
  return attract(target, particle, -strength);
}

Color Algorithms

Palette Generation

javascript
// Complementary
function complementary(hue) {
  return [(hue + 180) % 360];
}

// Triadic
function triadic(hue) {
  return [(hue + 120) % 360, (hue + 240) % 360];
}

// Analogous
function analogous(hue, spread = 30) {
  return [(hue - spread + 360) % 360, (hue + spread) % 360];
}

// Split complementary
function splitComplementary(hue) {
  return [(hue + 150) % 360, (hue + 210) % 360];
}

Color Interpolation

javascript
// Lerp between colors
function lerpColor(c1, c2, t) {
  colorMode(HSB);
  return color(
    lerp(hue(c1), hue(c2), t),
    lerp(saturation(c1), saturation(c2), t),
    lerp(brightness(c1), brightness(c2), t)
  );
}

// Palette from noise
function noiseColor(t, palette) {
  let n = noise(t) * (palette.length - 1);
  let i = floor(n);
  let f = n - i;
  return lerpColor(palette[i], palette[i + 1], f);
}

Pattern Algorithms

Truchet Tiles

javascript
function truchetTile(x, y, size, type) {
  push();
  translate(x, y);
  
  if (type === 0) {
    arc(0, 0, size, size, 0, HALF_PI);
    arc(size, size, size, size, PI, PI + HALF_PI);
  } else {
    arc(size, 0, size, size, HALF_PI, PI);
    arc(0, size, size, size, PI + HALF_PI, TWO_PI);
  }
  
  pop();
}

Voronoi

javascript
// Simple Voronoi via distance check
function voronoi(points) {
  for (let x = 0; x < width; x++) {
    for (let y = 0; y < height; y++) {
      let closest = 0;
      let minDist = Infinity;
      
      for (let i = 0; i < points.length; i++) {
        let d = dist(x, y, points[i].x, points[i].y);
        if (d < minDist) {
          minDist = d;
          closest = i;
        }
      }
      
      stroke(points[closest].color);
      point(x, y);
    }
  }
}

Seeded Randomness

javascript
// Use seed for reproducibility
let seed = 12345;
randomSeed(seed);
noiseSeed(seed);

// Or generate from string
function hashCode(str) {
  let hash = 0;
  for (let i = 0; i < str.length; i++) {
    hash = ((hash << 5) - hash) + str.charCodeAt(i);
    hash = hash & hash;
  }
  return hash;
}

randomSeed(hashCode("my-artwork-2024"));

Creative Coding Tools

Tool Language Best For
p5.js JavaScript Beginners, web
Processing Java Desktop, print
Three.js JavaScript 3D, WebGL
TouchDesigner Visual Real-time, AV
Hydra JavaScript Live visuals
Shadertoy GLSL GPU shaders
Nannou Rust Performance


Related Skills

Complementary Skills (Use Together)

Alternative Skills (Similar Purpose)

Prerequisite Skills (Learn First)

  • None required - includes foundational creative coding patterns

References

  • references/noise-recipes.md - Noise function patterns
  • references/color-palettes.md - Curated color schemes
  • references/shader-patterns.md - GLSL snippets

Didn't find tool you were looking for?

Be as detailed as possible for better results