Node Recipe 02: The Crowd

    All the recipes in this series: Recipe 00, Recipe 01, Recipe 02

    Node Concepts

    • Using an agent simulation library to generate complex behavior
    • Passing dictionaries between Max and Node


    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?


    • flocc : general purpose NPM simulation library
    • dict : pass a dictionary of state information between Max and Node

    Things to Note

    1. 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.
    2. 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.
    3. 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


    • 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.