Loading
The first version made only two things: singular clumps and expanding dust. One repulsion zone changed everything.
Launch the simulation
0101 / 09The first version of Particle Life was dead in two different ways.
When two colors attracted each other, they accelerated inward until they occupied almost the same point. A thousand particles became a handful of brilliant singularities: visually intense, physically useless. When the matrix said they should repel, they spread until the screen became evenly distributed dust. There were no membranes, no chains, no rotating arms, no structures that could persist long enough to become interesting.
Every matrix produced a variation of collapse or dispersal.
This was not a tuning problem. I could lower the force, increase friction, reduce the particle count, or choose gentler values, but all I changed was how quickly the same failure arrived. The shape of the force was wrong. I was asking attraction to create both togetherness and separation, and attraction only knows how to do the first.
The project began working when the particles learned to keep their distance.
The decisive idea: Stable structure needs two opposing instructions: come closer when you are far enough away, but move apart when you become too close.
This uses the engine equation and tuning ranges. f is normalized; one neighbor contributes Δv = f × 80 × 1/60 before friction.
Particle Life begins with objects too simple to deserve the word agent.
Each particle has a position, a velocity, and one of five color types. It has no memory, goal, sensor, metabolism, or model of the world. At every physics step it looks only at nearby particles and asks two questions:
The first answer selects a value from a 5×5 interaction matrix. The second answer passes through a force curve. Together they decide whether this particle accelerates toward or away from its neighbor.
That is the full behavioral vocabulary. Twenty-five directional relationships, one distance law, repeated across thousands of local encounters sixty times per simulated second.
The ambition was not to animate something that looked alive. Animation would let me draw the result I wanted. The ambition was to specify local physics and then lose control of the global result—to create the conditions under which structure might appear without placing that structure anywhere in the code.
I wrote about the broader distinction in Emergence vs Complexity. Particle Life is the concrete experiment: if the rule really is simple, you should be able to touch it, change it, and watch the consequence propagate.
The failed force was strongest where it should have been most cautious.
Imagine two particles that attract. If their force remains attractive all the way down to zero distance, every step moves them closer. Closer particles feel another pull, gain more inward velocity, and approach the numerical singularity at the same position. Friction can slow the collapse but cannot create a distance at which the pair has a reason to stop.
Now reverse the matrix value. A repelling pair moves apart until it leaves the interaction radius. Once outside, the force becomes zero and the particles remain separated. Scale both cases to two thousand particles and the result is inevitable:
| Relationship | Local result | Global result |
|---|---|---|
| Attraction to zero distance | Pairs collapse | Dense singular clumps |
| Repulsion inside the radius | Pairs separate | Uniform expanding dust |
The missing behavior was an equilibrium: a distance where the instruction changes sign.
The shipped engine normalizes pair distance as t = d / R, where d is the distance between two particles and R is the maximum interaction radius. It then divides that radius into two active zones.
0 ≤ t < β universal repulsion
β ≤ t < 1 matrix attraction or repulsion
t ≥ 1 no forceThe close zone ignores color and matrix values. Every pair repels there. In the middle zone, the 5×5 matrix takes control. Beyond R, the pair does not interact.
The matrix value controls only the middle zone. The close-range repulsion is universal, so attraction can settle instead of collapsing.
In the engine, the scalar force is this piecewise function:
const t = distance / interactionRadius;
const force = t < beta
? t / beta - 1
: matrix[myType][theirType] *
(1 - Math.abs(2 * t - 1 - beta) / (1 - beta));The first branch rises from -1 at zero distance to 0 at β. It is always repulsive. The second is a triangular well: zero at both ends, strongest in the middle, and signed by the interaction matrix.
The defaults are R = 100 px and β = 0.3. That places the boundary at:
β × R = 0.3 × 100 px = 30 pxFor an attractive pair, the middle zone pulls inward while the inner zone pushes outward. The change occurs at 30 pixels, so that is where the pair settles. The test suite does not merely assert the equation: it simulates a real pair and measures its final separation. At the tuned parameters, the result is 30.00 pixels to the test tolerance.
A repelling pair behaves differently. Both zones push it outward until it approaches R; beyond 100 pixels it feels nothing. The same curve therefore supports stable proximity and clean separation without special cases for either relationship.
Two particles settling at a distance is not life. It is barely a structure. But it introduces something the first version could never produce: persistent empty space.
That space matters. A cluster whose members cannot occupy the same point has an interior shape. A chain has link length. A membrane can resist compression. Several color types can form adjacent regions instead of collapsing into one coordinate. Once the system can preserve distance, the matrix can organize that distance.
The global forms are not encoded as templates:
Galaxy class that draws rotating arms.Each particle sums local pair forces, updates its velocity, and wraps around the world. The named patterns are descriptions applied after the fact. “Galaxy,” “Cells,” and “Soup” are matrices, not animation routines.
This is the point where the word emergence earns its place. The rule contains a preferred pair distance. It does not contain a rotating five-color pursuit loop. That loop appears only when many directional relationships act simultaneously through space and time.
It is tempting to look at forceScale, friction, R, and β as four sliders that can be tuned by feel. The engine taught me otherwise.
Friction is applied on every fixed step. With the original force strength, it capped terminal speeds below the acceptance range no matter how attractive the matrix became. Increasing matrix values could not solve a force budget that was physically unreachable. I had to measure the system, search the allowed parameter grid, and tune the curve as a unit.
The resulting defaults are not sacred constants of nature. They are a measured operating point for this canvas scale, particle count, timestep, and visual language. Change the timestep or friction model and the same numbers no longer mean the same thing.
That distinction is important: the emergent behavior is not magic hidden in 0.3. It is the consequence of relationships among parameters, repeated at scale.
Particle Life produces lifelike motion. It does not prove that the particles are alive.
They do not reproduce, consume energy, adapt, preserve information across generations, or maintain themselves against an environment. Calling a rotating cluster an organism would replace the interesting question with an easy metaphor.
What the simulation does show is narrower and, to me, more useful: behaviors we instinctively describe with biological language can arise from particles that possess none of the properties we associate with biology. Chasing can emerge without desire. Cohesion can emerge without loyalty. A boundary can emerge without a builder.
Known, measured, unknown: The force law is known. Pair spacing and system metrics are measured. Whether visual “aliveness” corresponds to anything scientifically deeper remains open.
That uncertainty is not a defect. It is the reason to build an instrument instead of a video. You can change the rule and challenge the impression yourself.
Open the Particle Life simulation and choose Galaxy.
Do not change anything for the first fifteen seconds. Watch the particles establish spacing before the larger arms become legible. Then pause the simulation and change exactly one positive matrix cell toward zero. Resume and observe for another fifteen seconds.
The useful question is not “does it still look beautiful?” Ask something narrower:
In Part 2, I will turn the matrix from a wall of twenty-five sliders into a readable language—and show why direction is what makes one color chase while another flees.
More to read
The matrix is not a palette or a control panel. It is a directional language for attraction, repulsion, pursuit, and structure.
Fixed time, deterministic seeds, a toroidal world, and the spatial hash that lets two thousand particles remain an experiment.
The renderer is not decoration. It makes distance, motion, relationships, and failure legible without changing the physics underneath.