/**
- ═══════════════════════════════════════════════════════════════════════════
P5.JS GENERATIVE ART - BEST PRACTICES- ═══════════════════════════════════════════════════════════════════════════
- This file shows STRUCTURE and PRINCIPLES for p5.js generative art.
- It does NOT prescribe what art you should create.
- Your algorithmic philosophy should guide what you build.
- These are just best practices for how to structure your code.
- ═══════════════════════════════════════════════════════════════════════════ */
// ============================================================================ // 1. PARAMETER ORGANIZATION // ============================================================================ // Keep all tunable parameters in one object // This makes it easy to: // - Connect to UI controls // - Reset to defaults // - Serialize/save configurations
let params = { // Define parameters that match YOUR algorithm // Examples (customize for your art): // - Counts: how many elements (particles, circles, branches, etc.) // - Scales: size, speed, spacing // - Probabilities: likelihood of events // - Angles: rotation, direction // - Colors: palette arrays
seed: 12345,
// define colorPalette as an array -- choose whatever colors you'd like ['#d97757', '#6a9bcc', '#788c5d', '#b0aea5']
// Add YOUR parameters here based on your algorithm
};
// ============================================================================ // 2. SEEDED RANDOMNESS (Critical for reproducibility) // ============================================================================ // ALWAYS use seeded random for Art Blocks-style reproducible output
function initializeSeed(seed) { randomSeed(seed); noiseSeed(seed); // Now all random() and noise() calls will be deterministic }
// ============================================================================ // 3. P5.JS LIFECYCLE // ============================================================================
function setup() { createCanvas(800, 800);
// Initialize seed first
initializeSeed(params.seed);
// Set up your generative system
// This is where you initialize:
// - Arrays of objects
// - Grid structures
// - Initial positions
// - Starting states
// For static art: call noLoop() at the end of setup
// For animated art: let draw() keep running
}
function draw() { // Option 1: Static generation (runs once, then stops) // - Generate everything in setup() // - Call noLoop() in setup() // - draw() doesn't do much or can be empty
// Option 2: Animated generation (continuous)
// - Update your system each frame
// - Common patterns: particle movement, growth, evolution
// - Can optionally call noLoop() after N frames
// Option 3: User-triggered regeneration
// - Use noLoop() by default
// - Call redraw() when parameters change
}
// ============================================================================ // 4. CLASS STRUCTURE (When you need objects) // ============================================================================ // Use classes when your algorithm involves multiple entities // Examples: particles, agents, cells, nodes, etc.
class Entity { constructor() { // Initialize entity properties // Use random() here - it will be seeded }
update() {
// Update entity state
// This might involve:
// - Physics calculations
// - Behavioral rules
// - Interactions with neighbors
}
display() {
// Render the entity
// Keep rendering logic separate from update logic
}
}
// ============================================================================ // 5. PERFORMANCE CONSIDERATIONS // ============================================================================
// For large numbers of elements: // - Pre-calculate what you can // - Use simple collision detection (spatial hashing if needed) // - Limit expensive operations (sqrt, trig) when possible // - Consider using p5 vectors efficiently
// For smooth animation: // - Aim for 60fps // - Profile if things are slow // - Consider reducing particle counts or simplifying calculations
// ============================================================================ // 6. UTILITY FUNCTIONS // ============================================================================
// Color utilities function hexToRgb(hex) { const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; }
function colorFromPalette(index) { return params.colorPalette[index % params.colorPalette.length]; }
// Mapping and easing function mapRange(value, inMin, inMax, outMin, outMax) { return outMin + (outMax - outMin) * ((value - inMin) / (inMax - inMin)); }
function easeInOutCubic(t) { return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2; }
// Constrain to bounds function wrapAround(value, max) { if (value < 0) return max; if (value > max) return 0; return value; }
// ============================================================================ // 7. PARAMETER UPDATES (Connect to UI) // ============================================================================
function updateParameter(paramName, value) { params[paramName] = value; // Decide if you need to regenerate or just update // Some params can update in real-time, others need full regeneration }
function regenerate() { // Reinitialize your generative system // Useful when parameters change significantly initializeSeed(params.seed); // Then regenerate your system }
// ============================================================================ // 8. COMMON P5.JS PATTERNS // ============================================================================
// Drawing with transparency for trails/fading function fadeBackground(opacity) { fill(250, 249, 245, opacity); // Anthropic light with alpha noStroke(); rect(0, 0, width, height); }
// Using noise for organic variation function getNoiseValue(x, y, scale = 0.01) { return noise(x * scale, y * scale); }
// Creating vectors from angles function vectorFromAngle(angle, magnitude = 1) { return createVector(cos(angle), sin(angle)).mult(magnitude); }
// ============================================================================ // 9. EXPORT FUNCTIONS // ============================================================================
function exportImage() { saveCanvas('generative-art-' + params.seed, 'png'); }
// ============================================================================ // REMEMBER // ============================================================================ // // These are TOOLS and PRINCIPLES, not a recipe. // Your algorithmic philosophy should guide WHAT you create. // This structure helps you create it WELL. // // Focus on: // - Clean, readable code // - Parameterized for exploration // - Seeded for reproducibility // - Performant execution // // The art itself is entirely up to you! // // ============================================================================