Skip to content
Sample of Inverse-distance Attractor Network

openprocessing_p5js · AttractorNetwork

Inverse-distance Attractor Network

A population of point-agents, each carrying a position and a velocity, mutually attracted by an inverse-distance force F = G / max(d, d_min)^alpha along the displacement vector. The resulting dynamics produce organic, filament-like network patterns — the canonical OpenProcessing 'attractor network' look.

Original: https://openprocessing.org/browse/?q=Maths&time=anytime&type=tags

▶ Try the live demo (JS port) ▶ Run reference.py via Pyodide 10 formulas have instant JS ports. The Pyodide path runs the actual Python in your browser — first load is ~6 MB, then instant.

Family
openprocessing_p5js
Source
openprocessing · p5.js
Evolution
particle
Render
trail_accumulation
Complexity
high
Agents
60
Year
2015
Author
community (OpenProcessing) / Pierre Bail 'Eyes attractor' school

Math essence

For every ordered pair (i, j): d = p_j - p_i; F = G * d / max(|d|, d_min)^alpha. Sum over j, integrate explicit Euler with capped acceleration and speed, fade trails onto canvas.

Parameters

Name Type Default Range Description
dim int 512 200–1200 Square canvas side length.
num_agents int 60 8–400 Number of agents.
gravity float 90 0–1000 Force constant G.
power float 2 0.5–4 Inverse-distance exponent alpha.
min_dist float 4 0.5–64 Soft-core distance below which repulsion dominates.
max_speed float 3.5 0.1–12 Velocity clamp.
max_force float 0.35 0.01–3 Acceleration clamp.
friction float 0.02 0–0.5 Per-tick velocity damping.
line_alpha float 0.18 0.01–0.6 Trail opacity per stamp.
bg_color tuple 12,12,22 — Background canvas color.
ink_color tuple 240,220,180 — Trail ink color.
seed int null 0–999999

Reference

First 60 lines of reference.py. Full source: library_external/openprocessing_p5js/AttractorNetwork/reference.py

from __future__ import annotations

from typing import ClassVar

import numpy as np


class AttractorNetwork:
    """Network of agents mutually attracted by an inverse-distance force.

    This is the canonical *OpenProcessing* "attractor network" sketch family
    (cf. <https://openprocessing.org/browse/?q=Maths&time=anytime&type=tags>;
    "Eyes attractor" by Pierre Bail and similar agent-network sketches that
    have been forked thousands of times). Each agent carries a position and a
    velocity; on every tick we compute, for every ordered pair ``(i, j)``,
    the displacement vector ``d = p_j - p_i`` and apply a force of magnitude
    ``G * m_i * m_j / max(|d|, eps)**alpha`` along the unit displacement.

    Because the force law is symmetric, agents end up forming filaments: they
    are pulled toward dense regions until they collide, at which point short-
    range repulsion takes over. We cap both speed and acceleration, integrate
    with explicit Euler, and let the trails fade onto a running canvas. A
    small random kick on respawn keeps the network from collapsing into a
    single point.

    The system exhibits organic network / web / mycelium-like patterns — the
    classic "attractor" look that defines the genre on OpenProcessing.
    """

    family: ClassVar[str] = "openprocessing_p5js"
    sketch: ClassVar[str] = "attractorNetwork"

    def __init__(
        self,
        dim: int = 512,
        num_agents: int = 60,
        gravity: float = 90.0,
        power: float = 2.0,
        min_dist: float = 4.0,
        max_speed: float = 3.5,
        max_force: float = 0.35,
        friction: float = 0.02,
        line_alpha: float = 0.18,
        bg_color: tuple[int, int, int] = (12, 12, 22),
        ink_color: tuple[int, int, int] = (240, 220, 180),
        seed: int | None = None,
    ) -> None:
        self.dim = dim
        self.num_agents = num_agents
        self.gravity = gravity
        self.power = power
        self.min_dist = min_dist
        self.max_speed = max_speed
        self.max_force = max_force
        self.friction = friction
        self.line_alpha = line_alpha
        self.bg_color = np.array(bg_color, dtype=np.float32)
        self.ink_color = np.array(ink_color, dtype=np.float32)
        self._seed = seed
        self.reset()

Try running it locally

The reference implementation is self-contained Python with numpy. Install the package and run:

python library_external/openprocessing_p5js/AttractorNetwork/reference.py

Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.

More from openprocessing · p5.js

See all openprocessing_p5js artworks →