- Jump To … +
  ./source/core/animation-loop.js ./source/core/display-cycle.js ./source/core/document-root-elements.js ./source/core/document.js ./source/core/events.js ./source/core/init.js ./source/core/library.js ./source/core/random-seed.js ./source/core/shared-vars.js ./source/core/snippets.js ./source/core/system-flags.js ./source/core/user-interaction.js ./source/core/utilities.js ./source/factory/action.js ./source/factory/anchor.js ./source/factory/animation.js ./source/factory/array-pool.js ./source/factory/bezier.js ./source/factory/block.js ./source/factory/canvas.js ./source/factory/cell-fragment.js ./source/factory/cell.js ./source/factory/cog.js ./source/factory/color.js ./source/factory/conic-gradient.js ./source/factory/coordinate.js ./source/factory/crescent.js ./source/factory/drag-zone.js ./source/factory/element.js ./source/factory/emitter.js ./source/factory/filter-engine-bluenoise-data.js ./source/factory/filter-engine.js ./source/factory/filter.js ./source/factory/font-attributes.js ./source/factory/gradient.js ./source/factory/grid.js ./source/factory/group.js ./source/factory/image-asset.js ./source/factory/keyboard-zone.js ./source/factory/line-spiral.js ./source/factory/line.js ./source/factory/loom.js ./source/factory/mesh.js ./source/factory/net.js ./source/factory/noise-asset.js ./source/factory/observe-update.js ./source/factory/oval.js ./source/factory/palette.js ./source/factory/particle-force.js ./source/factory/particle-history.js ./source/factory/particle-spring.js ./source/factory/particle-world.js ./source/factory/particle.js ./source/factory/pattern.js ./source/factory/phrase.js ./source/factory/picture.js ./source/factory/polygon.js ./source/factory/polyline.js ./source/factory/quadratic.js ./source/factory/quaternion.js ./source/factory/radial-gradient.js ./source/factory/raw-asset.js ./source/factory/reaction-diffusion-asset.js ./source/factory/rectangle.js ./source/factory/render-animation.js ./source/factory/shape.js ./source/factory/spiral.js ./source/factory/sprite-asset.js ./source/factory/stack.js ./source/factory/star.js ./source/factory/state.js ./source/factory/tetragon.js ./source/factory/ticker.js ./source/factory/tracer.js ./source/factory/tween.js ./source/factory/unstacked-element.js ./source/factory/vector.js ./source/factory/video-asset.js ./source/factory/wheel.js ./source/mixin/anchor.js ./source/mixin/asset-advanced-functionality.js ./source/mixin/asset-consumer.js ./source/mixin/asset.js ./source/mixin/base.js ./source/mixin/cascade.js ./source/mixin/cell-key-functions.js ./source/mixin/delta.js ./source/mixin/display-shape.js ./source/mixin/dom.js ./source/mixin/entity.js ./source/mixin/filter.js ./source/mixin/mimic.js ./source/mixin/path.js ./source/mixin/pattern.js ./source/mixin/pivot.js ./source/mixin/position.js ./source/mixin/shape-basic.js ./source/mixin/shape-curve.js ./source/mixin/shape-path-calculation.js ./source/mixin/styles.js ./source/mixin/tween.js

- §

  # Force factory

  The Scrawl-canvas particle physics engine is a simple system designed to allow developers a way to add particle-based effects to their canvas animation scenes. The physics engine is built on top of the following components:

  - Particle objects, which represent a 3-dimensional coordinate - based on a Scrawl-canvas Vector object - and include a history of recent positions which we can use to determine how to display that particle on screen.
  - History arrays which can be pooled (reused) to cut down on Array creation and distruction during the animation.
  - Force objects which define the general and occasional forces to be applied to each particle in the system as the animation progresses - a gravity force object is pre-defined by Scrawl-canvas.
  - Spring objects used to define a constraint (connection) between two particles in a system.
  - World objects where we can store attributes and values used by various objects; these attributes can be set up so that they will be inherited by clones of the World object. We can also influence the speed of the physics animation here.

  We do not have to handle particle generation and manipulation ourselves. Instead, Scrawl-canvas gives us three dedicated entitys which we use to add particle animation effects to the canvas scene. These entitys are:

  - Tracer - this entity generates a single non-recycled (in other words: long lasting) particle with a history, which we can use to display trace effects in the animation.
  - Emitter - an entity which generates a stream of short-lived, recycled particles, each with its own history. Emitters are highly versatile entitys which can generate a wide range of effects.
  - Net - a (generally) larger entity which uses both forces and springs to manage the animation of its non-recycled particles. Note that other artefacts can use Net particles as a reference for their own positioning.

  #### Particle physics

  The Scrawl-canvas particle physics engine system is based on a fairly classical understanding of particle kinetics (applying forces and constraints to a small, spherical object in 3D space) and kinematics (the movement of the small object in response to the forces and constraints applied to it).

  A Scrawl-canvas Force object is, essentially, a wrapper around an `action` function which calculates a force operating on a particle. The force object must have a unique name. Also …

  The action function must accept three arguments, in the following order:

  - a Particle object
  - a World object
  - a Cell object

  The function must add the result of its calculation to the Particle object’s `load` Vector.

  … See the gravity force, below, for an example of how to construct a Force object.

  The Force factory uses the Base mixin, thus Force objects can be cloned and killed like other Scrawl-canvas objects. Force objects are stored in the `scrawl.library.force` section of the Scrawl-canvas library object.

- §

  #### Demos:

  - particles-001 - Emitter entity, and Particle World, basic functionality
  - particles-007 - Particle Force objects: generation and functionality
  - particles-008 - Net entity: generation and basic functionality, including Spring objects
  - particles-009 - Net particles: drag-and-drop functionality
  - particles-012 - Use Net entity particles as reference coordinates for other artefacts
- §

  #### Imports

      import { constructors } from '../core/library.js';

      import { doCreate, isa_fn, mergeOver, pushUnique, λnull, Ωempty } from '../core/utilities.js';

      import { releaseVector, requestVector } from './vector.js';

      import baseMix from '../mixin/base.js';

      import { FORCE, GRAVITY, T_FORCE } from '../core/shared-vars.js';

- §

  #### Force constructor

      const Force = function (items = Ωempty) {

          this.makeName(items.name);
          this.register();

          this.set(this.defs);

          this.set(items);

          if (!this.action) this.action = λnull;

          return this;
      };

- §

  #### Force prototype

      const P = Force.prototype = doCreate();
      P.type = T_FORCE;
      P.lib = FORCE;
      P.isArtefact = false;
      P.isAsset = false;

- §

  #### Mixins

      baseMix(P);

- §

  #### Force attributes

  - Attributes defined in the base mixin: name.

      const defaultAttributes = {

          action: null,
      };
      P.defs = mergeOver(P.defs, defaultAttributes);

- §

  #### Packet management

      P.packetFunctions = pushUnique(P.packetFunctions, ['action']);

- §

  #### Clone management

  No additional clone functionality required

- §

  #### Kill management

      P.kill = function () {

          this.deregister();

          return true;
      };

- §

  #### Get, Set, deltaSet

      const S = P.setters;

      S.action = function (item) {

          if (isa_fn(item)) this.action = item;
          else this.action = λnull;
      }

- §

  #### Factory

      let myRepellorBall = scrawl.makeWheel({

          name: 'big-ball',
          radius: 30,
      });

      scrawl.makeForce({

          name: 'example-repellor',
          action: (particle, world, host) => {

              let {load, position} = particle;

              let ballPosition = myRepellorBall.get('position');

              let tempVector = scrawl.requestVector(ballPosition).vectorSubtract(position);

              let magnitude = tempVector.getMagnitude();

              if (magnitude && magnitude < myRepellorBall.get('radius')) {

                  tempVector.scalarMultiply(1 / (magnitude / 1000));
                  load.vectorSubtract(tempVector)
              }
              scrawl.releaseVector(tempVector);
          },
      });

      export const makeForce = function (items) {

          if (!items) return false;
          return new Force(items);
      };

      constructors.Force = Force;

- §

  #### Gravity force

  Seeing as it’s such a common requirement, we pre-create it here

      makeForce({

          name: GRAVITY,
          action: (particle, world) => {

              const {mass, load} = particle;

              const c = requestVector();

              c.setFromVector(world.gravity).scalarMultiply(mass);
              load.vectorAdd(c);

              releaseVector(c);
          },
      });