main
1/**
2 * ═══════════════════════════════════════════════════════════════════════════
3 * P5.JS GENERATIVE ART - BEST PRACTICES
4 * ═══════════════════════════════════════════════════════════════════════════
5 *
6 * This file shows STRUCTURE and PRINCIPLES for p5.js generative art.
7 * It does NOT prescribe what art you should create.
8 *
9 * Your algorithmic philosophy should guide what you build.
10 * These are just best practices for how to structure your code.
11 *
12 * ═══════════════════════════════════════════════════════════════════════════
13 */
14
15// ============================================================================
16// 1. PARAMETER ORGANIZATION
17// ============================================================================
18// Keep all tunable parameters in one object
19// This makes it easy to:
20// - Connect to UI controls
21// - Reset to defaults
22// - Serialize/save configurations
23
24let params = {
25 // Define parameters that match YOUR algorithm
26 // Examples (customize for your art):
27 // - Counts: how many elements (particles, circles, branches, etc.)
28 // - Scales: size, speed, spacing
29 // - Probabilities: likelihood of events
30 // - Angles: rotation, direction
31 // - Colors: palette arrays
32
33 seed: 12345,
34 // define colorPalette as an array -- choose whatever colors you'd like ['#d97757', '#6a9bcc', '#788c5d', '#b0aea5']
35 // Add YOUR parameters here based on your algorithm
36};
37
38// ============================================================================
39// 2. SEEDED RANDOMNESS (Critical for reproducibility)
40// ============================================================================
41// ALWAYS use seeded random for Art Blocks-style reproducible output
42
43function initializeSeed(seed) {
44 randomSeed(seed);
45 noiseSeed(seed);
46 // Now all random() and noise() calls will be deterministic
47}
48
49// ============================================================================
50// 3. P5.JS LIFECYCLE
51// ============================================================================
52
53function setup() {
54 createCanvas(800, 800);
55
56 // Initialize seed first
57 initializeSeed(params.seed);
58
59 // Set up your generative system
60 // This is where you initialize:
61 // - Arrays of objects
62 // - Grid structures
63 // - Initial positions
64 // - Starting states
65
66 // For static art: call noLoop() at the end of setup
67 // For animated art: let draw() keep running
68}
69
70function draw() {
71 // Option 1: Static generation (runs once, then stops)
72 // - Generate everything in setup()
73 // - Call noLoop() in setup()
74 // - draw() doesn't do much or can be empty
75
76 // Option 2: Animated generation (continuous)
77 // - Update your system each frame
78 // - Common patterns: particle movement, growth, evolution
79 // - Can optionally call noLoop() after N frames
80
81 // Option 3: User-triggered regeneration
82 // - Use noLoop() by default
83 // - Call redraw() when parameters change
84}
85
86// ============================================================================
87// 4. CLASS STRUCTURE (When you need objects)
88// ============================================================================
89// Use classes when your algorithm involves multiple entities
90// Examples: particles, agents, cells, nodes, etc.
91
92class Entity {
93 constructor() {
94 // Initialize entity properties
95 // Use random() here - it will be seeded
96 }
97
98 update() {
99 // Update entity state
100 // This might involve:
101 // - Physics calculations
102 // - Behavioral rules
103 // - Interactions with neighbors
104 }
105
106 display() {
107 // Render the entity
108 // Keep rendering logic separate from update logic
109 }
110}
111
112// ============================================================================
113// 5. PERFORMANCE CONSIDERATIONS
114// ============================================================================
115
116// For large numbers of elements:
117// - Pre-calculate what you can
118// - Use simple collision detection (spatial hashing if needed)
119// - Limit expensive operations (sqrt, trig) when possible
120// - Consider using p5 vectors efficiently
121
122// For smooth animation:
123// - Aim for 60fps
124// - Profile if things are slow
125// - Consider reducing particle counts or simplifying calculations
126
127// ============================================================================
128// 6. UTILITY FUNCTIONS
129// ============================================================================
130
131// Color utilities
132function hexToRgb(hex) {
133 const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
134 return result ? {
135 r: parseInt(result[1], 16),
136 g: parseInt(result[2], 16),
137 b: parseInt(result[3], 16)
138 } : null;
139}
140
141function colorFromPalette(index) {
142 return params.colorPalette[index % params.colorPalette.length];
143}
144
145// Mapping and easing
146function mapRange(value, inMin, inMax, outMin, outMax) {
147 return outMin + (outMax - outMin) * ((value - inMin) / (inMax - inMin));
148}
149
150function easeInOutCubic(t) {
151 return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
152}
153
154// Constrain to bounds
155function wrapAround(value, max) {
156 if (value < 0) return max;
157 if (value > max) return 0;
158 return value;
159}
160
161// ============================================================================
162// 7. PARAMETER UPDATES (Connect to UI)
163// ============================================================================
164
165function updateParameter(paramName, value) {
166 params[paramName] = value;
167 // Decide if you need to regenerate or just update
168 // Some params can update in real-time, others need full regeneration
169}
170
171function regenerate() {
172 // Reinitialize your generative system
173 // Useful when parameters change significantly
174 initializeSeed(params.seed);
175 // Then regenerate your system
176}
177
178// ============================================================================
179// 8. COMMON P5.JS PATTERNS
180// ============================================================================
181
182// Drawing with transparency for trails/fading
183function fadeBackground(opacity) {
184 fill(250, 249, 245, opacity); // Anthropic light with alpha
185 noStroke();
186 rect(0, 0, width, height);
187}
188
189// Using noise for organic variation
190function getNoiseValue(x, y, scale = 0.01) {
191 return noise(x * scale, y * scale);
192}
193
194// Creating vectors from angles
195function vectorFromAngle(angle, magnitude = 1) {
196 return createVector(cos(angle), sin(angle)).mult(magnitude);
197}
198
199// ============================================================================
200// 9. EXPORT FUNCTIONS
201// ============================================================================
202
203function exportImage() {
204 saveCanvas('generative-art-' + params.seed, 'png');
205}
206
207// ============================================================================
208// REMEMBER
209// ============================================================================
210//
211// These are TOOLS and PRINCIPLES, not a recipe.
212// Your algorithmic philosophy should guide WHAT you create.
213// This structure helps you create it WELL.
214//
215// Focus on:
216// - Clean, readable code
217// - Parameterized for exploration
218// - Seeded for reproducibility
219// - Performant execution
220//
221// The art itself is entirely up to you!
222//
223// ============================================================================