Week 7 — Harmonic Motion and Animation
Harmonic Motion with noise
Random on Separate Refresh
More control over using the random and noise functions
Example link: random with modulos and noise
The same example is also in the 7.1 code folder.
Repetition & Oscillation and Linear Motion
In this section, there is discussion on two types of animation.
- Repetition - Animation that repeats from the beginning
- Repetition uses modulus to start from beginning
- Oscillation - Animation that swings back and forth like a pendulum
- Uses sine and cosine functions to oscillate between -1 and 1.
Examples - Repetitive motion
var x = 0;
function setup(){
createCanvas(400, 400);
noStroke();
}
function draw(){
background(220);
translate(0, height/4);
fill(255, 0, 0);
rect(x, 0, 100, 100);
x++;
// Using modulo is much better than using a conditional here.
x = x % width;
}
- Other words to describe oscillating motion are periodic motion or harmonic motion.
Examples - oscillating motion
let yPos;
var ySpeed = 1;
var radius = 50;
function setup() {
createCanvas(400, 400);
yPos = height / 2;
}
function draw() {
background(220);
yPos = yPos + ySpeed;
if (yPos + radius / 2 > height || yPos - radius / 2 < 0) {
ySpeed *= -1.0;
}
ellipse(width / 2, yPos, radius);
}
Sine and Cosine
Sine and cosine (waves) functions.
Amplitude: The maximum and minimum extents of oscillation. By default, sin() and cos() produce outputs in range -1 to 1.
Period (wavelength): The time taken to complete 1 oscillation. i.e., for the angle to increase from 0 to TWO_PI (radians).
Demo of sin(). Check the output of below code to see how a sine function behaves. Observe how the output value oscillates between -1 and 1.
function setup(){
createCanvas(400, 400);
//limits frame rate
frameRate(10);
}
function draw(){
background(255);
var val = sin(radians(frameCount));
console.log(val);
}
Observe that sine and cosine are offset (out of phase) by a value of PI/2.
Example: Elastic Motion
var radius = 50;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
var amplitude = height / 2 - radius / 2;
// - radius/2 for cosmetics: To account for radius during bounce
var y = sin(radians(frameCount)) * amplitude;
translate(width / 2, height / 2);
ellipse(0, y, radius);
}
This is similar to example in section 7.2 Linear motion. But there are no conditional statements to check or change the direction of motion.
Inspiration for Motion Graphics
Examples
Example code make the object go in a circle
var radius = 25;
var xSpeed = 4.0;
var angle = 0.0;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
translate(width / 2, height / 2);
var amplitude = height / 2 - radius / 2;
angle += 2.0;
var x = cos(radians(angle)) * amplitude;
var y = sin(radians(angle)) * amplitude;
fill(100);
ellipse(x, y, radius);
x += xSpeed;
}
Lissajous Curves
A Lissajous curve, also known as Lissajous figure or Bowditch curve, is the graph of a system of parametric equations x=A/sin; y=B/sin, which describe complex harmonic motion.
Wikipedia: Lissajous Curves
Render using the code in folder /7.4
Example sketches
The p5 sketches for this week, from the course repo.
7.1 — Harmonic Motionrepo ↗
/**
* Using modulo, random, and noise (perlin noise) to generate random unwinding shapes
* References: http://p5js.org/reference/#/p5/noise
* Aesthetic inspired by: John Whitney (https://www.youtube.com/watch?v=TbV7loKp69s)
**/
var shapeWidth;
var shapeHeight;
var vertCount;
var framesTilRefresh = 60;
function setup() {
createCanvas(windowWidth, windowHeight);
shapeWidth = random(width / 2);
shapeHeight = random(height / 2);
vertCount = 10;
}
function draw() {
background(100);
translate(width / 2, height / 2);
//using the modulo operator we can recalculate our vertCount every framesTilRefresh frames
if (frameCount % framesTilRefresh === 0) {
vertCount = floor(noise(frameCount) * 100);
}
if (frameCount % (framesTilRefresh * 6) === 0) {
shapeWidth = random(width / 2);
shapeHeight = random(height / 2);
}
makeShape(shapeWidth, shapeHeight, vertCount);
if (vertCount > 0 && frameCount % 4 === 0) {
vertCount--;
}
}
function makeShape(_width, _height, verts) {
noFill();
beginShape(LINE_STRIP);
for (var i = 0; i < verts; i++) {
var x = cos((i * verts) / TWO_PI) * _width;
var y = sin((i * verts) / TWO_PI) * _height;
curveVertex(x, y);
}
endShape();
}7.2 — Linear Motionrepo ↗
let yPos;
var ySpeed = 1;
var radius = 50;
function setup() {
createCanvas(400, 400);
yPos = height / 2;
}
function draw() {
background(220);
yPos = yPos + ySpeed;
if (yPos + radius / 2 > height || yPos - radius / 2 < 0) {
ySpeed *= -1.0;
}
ellipse(width / 2, yPos, radius);
}7.3 — Elastic Motionrepo ↗
var radius = 25;
var xSpeed = 4.0;
var angle = 0.0;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
translate(width / 2, height / 2);
var amplitude = height / 2 - radius / 2;
angle += 2.0;
var x = cos(radians(angle)) * amplitude;
var y = sin(radians(angle)) * amplitude;
fill(100);
ellipse(x, y, radius);
x += xSpeed;
}7.4 — Lissajous Curvesrepo ↗
var periodOne = 125.0;
var periodTwo = 90.0;
var pointCount = 0;
var angle = 0;
var amplitude = 300;
function setup() {
createCanvas(600, 600);
background(220);
}
function draw() {
noFill();
strokeWeight(1);
stroke(100);
translate(width / 2, height / 2);
if (pointCount > 2250) {
noLoop();
}
beginShape();
for (var i = 0; i < pointCount; i++) {
angle = (i / periodOne) * TWO_PI;
var x = sin(angle) * amplitude;
angle = (i / periodTwo) * TWO_PI;
var y = sin(angle) * amplitude;
vertex(x, y);
}
endShape();
pointCount++;
}