// De Jong Attractor
//
// x(n+1) = sin(a·y) - cos(b·x)
// y(n+1) = sin(c·x) - cos(d·y)
export const WARMUP = { framesBeforeReady: 240 };
export const PARAMS = {
a: { value: 1.4, min: -3, max: 3, step: 0.01, label: "a", folder: "Dynamics" },
b: { value: -2.3, min: -3, max: 3, step: 0.01, label: "b", folder: "Dynamics" },
c: { value: 2.4, min: -3, max: 3, step: 0.01, label: "c", folder: "Dynamics" },
d: { value: -2.1, min: -3, max: 3, step: 0.01, label: "d", folder: "Dynamics" },
iterations: { value: 8000, min: 1000, max: 30000, step: 500, label: "Points/Frame", folder: "Performance" },
hue: { value: 30, min: 0, max: 360, step: 1, label: "Base Hue", folder: "Appearance" },
hueSpread: { value: 80, min: 0, max: 200, step: 1, label: "Hue Spread", folder: "Appearance" },
scale: { value: 200, min: 50, max: 500, step: 1, label: "Scale", folder: "Appearance" },
fade: { value: 0.0, min: 0, max: 0.2, step: 0.005, label: "Background Fade", folder: "Appearance" },
};
export const SHARE = {
bookmarked: ["a", "b", "c", "d", "iterations", "hue", "hueSpread", "scale", "fade"],
};
let state;
export function sketchSetup(p, w, h) {
p.colorMode(p.HSB, 360, 100, 100, 1);
p.background(0);
p.noStroke();
state = {
x: 0.1,
y: 0.1,
prevParams: null,
};
return state;
}
export function sketchDraw(p, w, h, params) {
const { a, b, c, d } = params;
// Detect parameter change — reset if dynamics changed
const prev = state.prevParams;
if (prev && (prev.a !== a || prev.b !== b || prev.c !== c || prev.d !== d)) {
p.background(0);
state.x = 0.1;
state.y = 0.1;
}
state.prevParams = { a, b, c, d };
// Optional fade effect
if (params.fade > 0) {
p.fill(0, 0, 0, params.fade);
p.rect(0, 0, w, h);
}
const cx = w / 2;
const cy = h / 2;
const sc = params.scale;
let x = state.x;
let y = state.y;
const n = params.iterations;
for (let i = 0; i < n; i++) {
const nx = Math.sin(a * y) - Math.cos(b * x);
const ny = Math.sin(c * x) - Math.cos(d * y);
x = nx;
y = ny;
const px = cx + x * sc;
const py = cy + y * sc;
// Color by angle from origin in attractor space — gives spatial color variation
const angle = Math.atan2(y, x);
const hue = ((params.hue + (angle / Math.PI) * params.hueSpread) % 360 + 360) % 360;
p.fill(hue, 85, 100, 0.05);
p.rect(px, py, 1, 1);
}
state.x = x;
state.y = y;
}