Node Recipe 02: The Crowd

Node Concepts
Using an agent simulation library to generate complex behavior
Passing dictionaries between Max and Node
Commentary
This time out, we're keeping things simple. Unlike previous recipes, we’re only using one NPM library (flocc), and making full use of its features to create a simple simulated crowd visualization.
Simple simulations like this can be super fascinating as emergent patterns, and complex behaviors arise from a set of simple rules. Starting with a simple agent/flocking simulation, we’ve expanded it with an additional “solitude” behavior that changes each agent’s attraction to other agents based on how much time they’ve been near or apart from others.
Consider what you would do with the output of such a simulation. How would you extend the behavior?
Ingredients
flocc : general purpose NPM simulation library
dict : pass a dictionary of state information between Max and Node
Things to Note
While our simulation is running, it sends out a dictionary for each clock tick that includes information about the simulation. This data was formatted to make it especially easy to pack into a Jitter Matrix using jit.fill after using jit.unpack to extract it.
Since there are a number of settings to configure for the simulation state, you can use a dictionary to avoid making a whole list of Max Handlers in the JS code. Inside of Javascript, we use Object.assign() to set the state that we’ve changed without erasing the existing contents.
To manipulate the simulation, try changing the values of the simulation settings. The settings break down like this:
Maxspeed: The maximum speed each agent can travel
Maxforce: The maximum speed change that can occur in each clock tick.
Awareness_range: sets the search radius that defines which other agents each agent responds to.
Goal: How much force to devote to traveling toward the target
Solitude: Determines how quickly avoidance behavior switches to attraction. Larger values mean greater time between those changes
Near: determines the radius to search when doing solitude testing
Too_close: sets the radius for general collision-avoidance behavior
Technique
The flocc library defines an “environment” which is the world in which the simulation will run. Once that is created, you can populate the environment with “agents” – individual entities that have internal state that exist in the world. Those agents can also have “rules” applied to them - functions that are called for each clock tick of the environment.
Behavior of each agent is determined by these rules. In our code, most of the actual behaviors are defined in the simbehavior.js file.
It should be noted that each agent in the simulation stores its internal state in a Javascript object (similar to a Max Dictionary). A lot of the work of creating a simulation like this is determining what will be considered a global state for the simulation as a whole and what states are associated with individual agents.
The existing simulation behavior could easily be extended by adding new functions to the simbehavior.js file and calling them from inside the motion() function.
Learn More: See all the articles in this series
by Andrew Benson on March 19, 2019