The basis of this type of motion is what's often referred to as *Brownian Motion*. Every frame a particle will pick a random point within a square constraint, and move closer to it

` ````
// update position with vector
this.x += (Math.random() * 2 - 1) * this.speed;
this.y += (Math.random() * 2 - 1) * this.speed;
```

though the code looks slightly different in this pen, the particles there operate on that principle. The red line shows the direction which the random point was picked, and can be hidden using the showVector setting.

**Example 1 : move towards random point**

The problem with this motion is that it looks too rigid, and not at all fluid. To solve this issue, I apply an easing to the vector..

**Example 2 : ease towards random point**

The basis of the easing is `vector = vector * a + randomDestination * (1 - a)`

, where `a`

is like an easing amount, as *a* gets larger the more of the original vector remains the same, and less of the random number gets added (`(1 - a)`

), the changes are smaller. As *a* gets smaller, the vector uses more of the random point and less of the vector, and the movement gets more erradic.

The code now looks like this:

` ````
// pick random destination
this.dx = (Math.random()*2-1) * settings.particleSpeed;
this.dy = (Math.random()*2-1) * settings.particleSpeed;
// update vector
this.vx = this.vx * settings.a + this.dx * (1 - settings.a);
this.vy = this.vy * settings.a + this.dy * (1 - settings.a);
// update position with vector
this.x += this.vx
this.y += this.vy
```

You should be able to see a more natural movement emerge with *a* between 0.9 and 1. This laso depends on speed and frame rate, but I've found that a value close to 0.98 tends to work well.

Another variation is to split *a*; istead of using `(1 - a)`

for the random multipler, to use a separate number (*b*). This way `a + b`

don't need to add up to 1

**Example 3: ease towards random point (with a and b)**

If the numbers *a* and *b* add up to less than 1 (and *b* is lager than 0), then they'll have a tendency to not travel far, and hover around the same spot, as the cumulative vector is constantly deminishing, and the random component is making shake in it's place. If the combined number (*a* + *b*) is larger than 1, they'll have a tendency to travel more because the cumulative vector is growing, and the random component is making the particle change with small increments.

So that concludes the basics of how I use use the vector of a particle and a new random position every frame to generate a somewhat fluid motion. With these basics in mind, it's time to do some experiments.

**Experiment 1 : sine × b**

I've added a sine wave multiplier to to the *b* component. If *b* is larger (positive or negative), it moves faster, if it's closer to 0, then the movement slows down. The relative speed is controlled by *b*, and how frequently it slows down and speeds up again is controlled using the cycle.

Below is the *update* function code (the initial step is set to random during setup)

` ````
// incerement step and reset to 0 once it reaches cycle
this.step = (this.step + 1) % settings.cycle;
// convert step to a number between 0 to 1
const phase = this.step / settings.cycle;
// map ramp value to a sine wave value
const p1 = Math.sin(phase * 3.14 * 2)
// set random destination (unchanged)
this.dx = (Math.random()*2-1) * settings.particleSpeed;
this.dy = (Math.random()*2-1) * settings.particleSpeed;
// update vector (added p1 to b)
this.vx = this.vx * settings.a + this.dx * settings.b * p1;
this.vy = this.vy * settings.a + this.dy * settings.b * p1;
// update position with vector
this.x += this.vx
this.y += this.vy
```

**Experiment 2 : sin & cos on a**

Instead of multiplying sin × *b*, I calculate the sine and the cosine, and compute x and y components using sine and cosine; `vx`

uses `a × sin`

and `vy`

uses `a × cos`

. This makes it so that the *x* and *y* components move faster and slower in an inverse relation. This creates a little more structured looking result. I've reduced the particle size and reduced the speed of fade to show how this motion ends up looking over time.

Other possibilities include maping the speed or other particle values to the amplitude of a frequency range taken from an audio source, like I've done here. Or a much smaller variation on example 2 here. Even with just a few parameters, there's lots to experiment with.

*Related: In my previous Post, Draw with loops, I show how I use trigonometry to affect change on a particle.*

Before getting into the details, I'll start by going through a basic canvas setup that will give me some of the basics. You can use available frameworks such as p5js as-well, but I prefer this method.

I've put in documentation into the js code of the details, but the important part is that I've created a `draw`

function that executes on every render frame. For now, I've only put in a function that fills the background with a red color, you will see it fade in, as it is using a low opacity.

The basis, at the lowest level, is a variable that goes(increments) from `0`

to `n`

then starts over again

The mechanics is that you have a variable `val`

that gets updated every time an update is called. If the value reaches a maximum `range`

value, it starts from beginning again. This is done using a modulo(`%`

) function `val = (val + 1) % range`

This is a class that will allow a variable to hold some basic values

` ````
// create a class to hold value and have built in incrementing functionality
function Looper (range, start) {
this.val = start || 0 // set value to start value if defined, or 1
this.range = range || 100 // set range to passed value or default to 0
this.norm = this.val / this.range // initialize normalized value (between 0 and 1)
this.update = function () {
this.val = (this.val + 1) % this.range // update value
this.norm = this.val / this.range // update normalize value (between 0 and 1)
}
}
```

to show how this works, I created a loop instance, which will go from 0 to 299
`var loop1 = new Looper(300, 0)`

and then inside the draw loop, I use it to draw a circle (using a custom function that takes x, y, and radius values)

`drawCircle(loop1.val - loop1.range / 2, 0, 50)`

and, also inside the draw loop, I update the loop and the loop values
`loop1.update()`

what you will see is that the circle will move along the x axis from -150 to 149, then go to -150 again and repeat indefinetly. This is because the value goes from 0 to 299 and is offset by -150.

now instead of using the value `val`

, I switch to using the normalized value `norm`

which will return a value between 0 and 1. The `range`

in this case becomes the number of steps between 0 and 1. *node that it will never be 1, because instead of a value of 1 it will skip back to 0*

This is the code I'm using to draw using a normalized value. (I offset it by `-0.5`

because my 0,0 point is in the middle)

` ````
drawCircle((loop1.norm - 0.5) * (canvas.width - 100), 0, 50)
```

The next step is to add a smoother back-and forth animation.

This is done using some simple trigonometry.

` ````
// in the loop function
this.sin = Math.sin(this.norm * Math.PI * 2)
//in the draw loop
drawCircle((loop1.sin) * (canvas.width/2), 0, 50)
```

to understand how this works, look at this graph. The *x* axis, in the ranges from 0 to 2 * PI, completes a full wave. Thy *y* axis ranges from -1 to +1. So to get a value that goes from 0, up to 1, then down to -1 and back to 0, we map the normalized value `norm`

to 2PI (so instead of ranging from 0 to 1 it ranges from 0 to 2PI)

*source: wikipedia*

Now the same thing with normalized the sine, so we have a range from 0 to 1

adding new variable called `sinNorm`

to the loop class

` ````
this.sinNorm = (this.sin + 1) / 2
```

and updating the draw function to utilize it.
```
drawCircle((loop1.sinNorm - 0.5) * (canvas.width), 0, 50)
```

Now I'm adding a cos value as-well and applying to y axis

` ````
// in loop class/function
this.cos = Math.cos(this.norm * Math.PI * 2) // get cosine value from norm normalized to [0, 2PI]
this.cosNorm = (this.cos + 1) / 2 // normalize cos to [0,1]
//in draw loop
var r = 50 // radius of circle (using it below to adjust range along x and y axis)
drawCircle((loop1.sin) * (canvas.width/2 - r), (loop1.cos) * (canvas.height/2 - r), r)
```

Now that that works and makes sense, I apply the create multipe particle instances that have multiple loopers mapped to position, size, and color

The magic happens in the `Particle`

class. I've set up 3 loopers for each particle, and using all of them to update the the x and y position. I'm also using the loopers to update the circle radius and color.

` ````
function Particle() {
// initialize loopers with random trange and offset
this.loop1 = new Looper(2000 + 200 * Math.random(), 860 * Math.random())
this.loop2 = new Looper(500 + 250 * Math.random(), 220 * Math.random())
this.loop3 = new Looper(120 + 20 * Math.random(), 140 * Math.random())
this.offset = Math.random() // some color offset for the color
this.draw = function (){
// set x,y, radius, and color params
var x = (this.loop1.sin) * (canvas.width/4 - 10) + (this.loop2.sin) * (canvas.width/6 - 10) + (this.loop3.sin) * 30
var y = (this.loop1.cos) * (canvas.height/4 - 10) + (this.loop2.cos) * (canvas.height/6 - 10) + (this.loop3.cos) * 30
var r = 0.5 + 8 * this.loop3.sinNorm * this.loop3.cosNorm // set the radius
var c = `hsla(${80 + 50 * (this.loop3.cosNorm + this.offset) * this.loop2.sinNorm}, ${100}%, ${50 + 10 * this.loop3.sin}%, ${0.5})`
drawCircle(x, y, r, c); // draw the circle
this.loop1.update() // update looper
this.loop2.update() // update looper
this.loop3.update() // update looper
}
}
```

]]>