Chapter 7 - Motion
Supanit Angsirikul
Velocity Simulation
Velocity Simulation
float d = 0.0; // Distance
float v = 0.5; // Velocity
float t = 0.0; // Time
void setup() {
size(1000, 100);
}
void draw() {
d = v * t;
t += 0.5;
background(0);
text("v = " + v, 10, 20);
ellipse(d, height/2, 30, 30);
if (d > width)
noLoop();
}
// Increase and decrease velocity and reset time
void keyPressed() {
if (key == 'a')
v += 0.5;
else if (key == 'z')
v -= 0.5;
t = 0;
}
Step
Step
float d = 0.0;
float step = 0.5;
void setup() {
size(1000, 100);
}
void draw() {
d += step;
background(0);
text("step = " + step, 10, 20);
ellipse(d, height/2, 30, 30);
if (d > width)
noLoop(); // d=0;
}
// Increase and decrease step and reset distance
void keyPressed() {
if (key == 'a')
step += 0.5;
else if (key == 'z')
step -= 0.5;
d = 0;
}
Direction
Direction
float x, y;
float stepX = 1.2, stepY = 1.5;
int dirX = 1, dirY = 1;
void setup() {
size(500, 300);
x = 0; y = height/2;
}
void draw() {
x += (stepX * dirX);
y += (stepY * dirY);
background(0);
text("stepX = " + stepX + ", stepY = " + stepY, 10, 20);
ellipse(x, y, 30, 30);
if (x < 0 || x > width)
dirX = -dirX;
if (y < 0 || y > height)
dirY = -dirY;
}
void keyPressed() {
if (key == 'a')
stepX += 0.3;
else if (key == 'z')
stepX -= 0.2;
else if (key == 's')
stepY += 0.3;
else if (key == 'x')
stepY -= 0.2;
}
Acceleration
Note : The motion of an object is caused by applied force.
Acceleration
float f = 0.15; // Force
float m = 5.0; // Mass
float a = 0.0; // Acceleration
float v = 0.0; // x-velocity
float d = 0; // distance
void setup() {
size(1000, 100);
}
void draw() {
a = f / m;
v += a; // New velocity = Original velocity + Acceleration d += v; // New position = Previous position + Velocity
background(0);
text("f = " + f + ", a = " + a + ", v = " + v, 10, 20);
ellipse(d, height/2, 30, 30);
if (d > width )
noLoop();
}
// Increase and decrease force and reset distance and velocity
void keyPressed() {
if (key == 'a')
f += 0.1;
else if (key == 'z’)
f -= 0.1;
d = 0;
v = 0;
}
Travel Speed
Travel Speed
float f = 0.15; // Force
float m = 5.0; // Mass
float a = 0.0; // Acceleration
float v = 0.0; // x-velocity
float d = 0; // distance
void setup() {
size(1000, 100);
}
void draw() {
a = f / m;
v += a;
d += v;
background(0);
text("a = " + a + ", v = " + v, 10, 20);
ellipse(d, height/2, 30, 30);
// start reduce force when move pass width/3
if (f > 0 && d > width/3 && a > 0.001)
f -= 0.01;
if (d > width ) {
// reset
a = 0; v = 0; d = 0; f = 0.15;
}
}
Acceleration without Force
float d = 0;
float stepX = 0.0;
float a = 0.05; // acceleration
void setup() {
size(1000, 100);
}
void draw() {
stepX += a;
d += stepX;
background(0);
text( "a = " + a + ", stepX = " + stepX, 10, 20);
ellipse(d, height/2, 30, 30);
// start reduce acceleration when move pass width/3
if (a > 0.001 && d > width/3)
a -= 0.001;
if (d > width ) {
// reset
a = 0.05; d = 0; stepX = 0.0;
}
}
Friction
Friction
float x = 0.0;
float stepX = 1.3;
float a = 0.05; // acceleration
float fr = 0.02; // friction
void setup() {
size(1000, 100);
smooth();
}
void draw() {
stepX += (a - fr);
x += stepX;
background(0);
text("a = " + a + " fr = " + fr, 10, 20);
ellipse(x, 70, 40, 40);
// start reduce acceleration when move pass width/3
if (a > 0.001 && x > width/3)
a -= 0.001;
if (x > width) {
// reset
a = 0.05; x = 0; stepX = 0.0; fr = 0.02;
}
}
// Increase and decrease friction
void keyPressed() {
if (key == 'a')
fr += 0.001;
else if (key == 'z')
fr -= 0.001;
a = 0.05; x = 0; stepX = 0.0;
}
Easing (Reduce Movement)
Easing (Reduce Movement)
float x = 0.0;
float easing = 0.05; // 0.0 -> 1.0
void setup() {
size(1000, 200);
smooth();
}
void draw() {
float target = mouseX;
x += (target - x) * easing; // มาจาก step = (target – x) * easing , แล้วจึงให้ x += step
background(0);
rect(mouseX-20, height-40, 40, 40);
ellipse(x, 70, 40, 40);
}
Easing
float x = 0.0;
float y = 0.0;
float easing = 0.05; // 0.0 -> 1.0
void setup() {
size(1000, 800);
smooth();
}
void draw() {
float targetX = mouseX;
x += (targetX - x) * easing; // มาจาก step = (target – x) * easing , แล้วจึงให้ x += step
float targetY = mouseY;
y += (targetY - y) * easing;
background(0);
rect(mouseX-20, mouseY, 40, 40);
ellipse(x, y, 40, 40);
}
no tail
void setup() {
size(1000, 100);
noStroke();
}
float x = 0.0;
void draw() {
fill(255);
background(0);
ellipse(x, 50, 50, 50);
if (++x > width)
noLoop();
}
Tailing
Tailing
void setup() {
size(1000, 100);
noStroke();
}
float x = 0.0;
void draw() {
// tails
fill(0, 12); // try varying the alpha value
rect(0, 0, width, height);
// circle
fill(255);
// fill(0, 255, 0); // try varying color
ellipse(x, 50, 50, 50);
if (++x > width)
noLoop();
}
Rotating Square with Tails
float w = 100;
float angle = 0.0;
void setup() {
size(600, 600);
noStroke();
}
void draw() {
fill(0, 12);
rect(0, 0, width, height);
fill(255, 0, 0);
// fill(random(255), 0, 0);
// fill(random(255), random(255), random(255));
translate(width/2, height/2);
rotate(angle);
// w += random(-5, 5);
rect(-width/3, -height/3, w, w);
angle += 0.02;
}
Dancing Comets
float speed = 0.015;
float radius;
float angle = 0;
float sx = 1.0;
float sy = 0.5;
void setup() {
size(800, 600);
noStroke();
radius = width/3;
textSize(15);
}
void draw() {
fill(0, 4);
rect(0, 0, width, height);
angle += speed;
float x = width/2 + (cos(angle * sy) * radius);
float y = height/2 + (sin(angle * sx) * radius);
fill(x, y, 255, x);
ellipse(x, y, 3, 3); // smaller circle
x = x + cos(angle * sx) * radius/2;
y = y + sin(angle * sy) * radius/2;
fill(y, 255, x, y);
ellipse(x, y, 11, 11); // larger circle
}
void keyPressed() {
if (key == 'a')
speed += 0.01;
else if (key == 'z')
speed -= 0.01;
else if (key == 's')
radius += 3;
else if (key == 'x')
radius -= 3;
text("speed = " + speed, 20, 30);
text("radius = " + radius, 20, 50);
}
Growing
float r = 20.0; // size
float step = 1.0;
int d = 1; // direction
void setup() {
size(200, 200);
noStroke();
frameRate(50);
fill(255, 0, 0);
}
void draw() {
r += step * d;
background(255);
ellipse(width/2, height/2, r, r);
if ((r > width) || (r < height/10))
d = -d;
}
Brownian Motion
Brownian Motion
void setup() {
size(200, 200);
background(0);
stroke(255);
}
float x = width/2;
float y = height/2;
void draw() {
x += random(-2, 2);
y += random(-2, 2);
point(x, y);
if (x < 0 || x > width || y < 0 || y > height) {
x = width/2;
y = height/2;
background(0);
}
}
Periodic Motion
float angle = 0.0; // Current angle
float speed = 0.1; // Speed of motion
float radius = 40.0; // Range of motion
float x = 0.0;
void setup() {
size(500, 100);
smooth();
noStroke();
}
void draw() {
angle += speed;
float y = sin(angle) * radius;
// no tail
fill(255);
background(0);
/* // tail
fill(0, 12);
rect(0, 0, width, height);
fill(255);
*/
ellipse((++x % width), height/2 + y, 20, 20);
// Vertical Periodic
// ellipse(width/2, height/2 + y, 20, 20);
}
Vibration with Amplitude
float speed = 0.1;
float angle = 0.0;
float amp1 = 15;
float amp2 = 3;
float amp3 = 5;
void setup() {
size(100, 100);
noStroke();
}
void draw() {
angle += speed;
background(0);
ellipse(25, 50+(sin(angle + PI)*amp1), 30, 30);
ellipse(55, 50+(sin(angle + HALF_PI)*amp2), 30, 30);
ellipse(85, 50+(sin(angle + TWO_PI)*amp3), 30, 30);
}
Swaying
void setup() {
size(200, 100);
stroke(255);
smooth();
}
float inc = 0.0;
void draw() {
inc += 0.01;
float angle = sin(inc)/10.0 + sin(inc*1.2)/20.0;
background(0);
tail(35, 9, angle/1.4);
tail(50, 8, angle/0.7);
tail(70, 12, angle);
tail(95, 10, angle/1.2);
tail(120, 5, angle*1.3);
tail(155, 7, angle*2);
}
void tail(int x, int units, float angle) {
pushMatrix();
translate(x, 100);
for (int i = units; i > 0; i--) {
strokeWeight(i);
line(0, 0, 0, -8);
translate(0, -8);
rotate(angle);
}
popMatrix();
}
shaking
float y;
float n = 0.0; // noise
float v = 0.4; // vary
float a = 25.0; // amplitude
void setup() {
size(300, 200);
stroke(255);
strokeWeight(20);
}
void draw() {
y = (noise(n) - 0.5) * a;
n += v;
background(0);
text("v = " + v + ", a = " + a, 10, 20);
line(0, height/2, width/2 - 10, height/2 + y);
}
void keyPressed() {
if (key == 'a')
v += 0.01;
else if (key == 'z')
v -= 0.01;
else if (key == 's')
a += 3;
else if (key == 'x')
a -= 3;
}
Elastic Motion 1
class Spring {
float M = 0.8; // Mass
float K = 0.2; // Spring constant
float D = 0.92; // Damping
float Rx = 100; // Rest position
float Ry = 100; // Rest position
float xpos; // Position x
float ypos; // Position y
float vx = 0.0; // Velocity x
float vy = 0.0; // Velocity y
float a = 0; // Acceleration
float f = 0; // Force
boolean released = false;
void move() {
f = -K * (xpos - Rx); // f=-Kx
a = f / M; // Set the acceleration, f=ma == a=f/m
vx = D * (vx + a); // Set the velocity in X axis
xpos += vx; // Updated x position
f = -K * (ypos - Ry); // f=-Ky
a = f / M; // Set the acceleration, f=ma == a=f/m
vy = D * (vy + a); // Set the velocity in Y axis
ypos += vy; // Updated y position
if (abs(vx) < 0.01 && abs(vy) < 0.01) {
vx = 0.0;
vy = 0.0;
released = false;
}
}
}
Damping is the gradual reduction of amplitude.
Elastic Motion 1 (cont.)
Spring s = new Spring();
void setup() {
size(300, 300);
fill(0);
s.Rx = s.xpos = width/2;
s.Ry = s.ypos = height/2;
}
void draw() {
background(200, 10);
if (s.released)
s.move();
ellipse(s.xpos, s.ypos, 30, 30);
}
void mousePressed() {
if (dist(mouseX, mouseY, s.xpos, s.ypos) < 10 && s.released == false) {
s.xpos = random(width);
s.ypos = random(height);
}
}
void mouseReleased() {
s.released = true;
}
Elastic Motion 2
class Spring {
float M = 0.8; // Mass
float K = 0.2; // Spring constant
float D = 0.92; // Damping
float Rx = 100; // Rest position
float Ry = 100; // Rest position
float xpos; // Position x
float ypos; // Position y
float vx = 0.0; // Velocity x
float vy = 0.0; // Velocity y
float a = 0; // Acceleration
float f = 0; // Force
boolean released = false;
void move() {
f = -K * (xpos - Rx); // f=-kx
a = f / M; // Set the acceleration, f=ma == a=f/m
vx = D * (vx + a); // Set the velocity
xpos += vx; // Updated x position
f = -K * (ypos - Ry); // f=-ky
a = f / M; // Set the acceleration, f=ma == a=f/m
vy = D * (vy + a); // Set the velocity
ypos += vy; // Updated y position
if (abs(vx)<0.01 && abs(vy) < 0.01) {
vx = 0.0;
vy = 0.0;
released = false;
}
}
}
Elastic Motion 2
int n = 9;
Spring [] s = new Spring[n];
void setup() {
size(300, 300);
for (int i = 0; i < n; i++) {
s[i] = new Spring();
s[i].xpos = random(width);
s[i].ypos = random(height);
s[i].Rx = s[i].xpos;
s[i].Ry = s[i].ypos;
}
}
void draw() {
background(200, 10);
for (int i=0; i< n; i++) {
if (s[i].released)
s[i].move();
ellipse(s[i].xpos, s[i].ypos, 10, 10);
}
for (int i = 0; i < n-1; i++)
line(s[i].xpos, s[i].ypos, s[i+1].xpos, s[i+1].ypos);
}
void mousePressed() {
for (int i = 0; i < n; i++)
if (dist(mouseX, mouseY, s[i].xpos, s[i].ypos) < 10 &&
s[i].released == false) {
s[i].xpos = random(width);
s[i].ypos = random(height);
}
}
void mouseReleased() {
for (int i = 0; i < n; i++)
s[i].released = true;
}
Elastic Motion 3
class Spring {
float M = 0.8; // Mass
float K = 0.2; // Spring constant
float D = 0.92; // Damping
float Rx = 100; // Rest position
float Ry = 100; // Rest position
float xpos; // Position x
float ypos; // Position y
float vx = 0.0; // Velocity x
float vy = 0.0; // Velocity y
float a = 0; // Acceleration
float f = 0; // Force
boolean released = false;
void move() {
f = -K * (ypos - Ry); // f=-ky
a = f / M; // Set the acceleration, f=ma == a=f/m
vy = D * (vy + a); // Set the velocity
ypos += vy; // Updated y position
if (abs(vx)<0.01 && abs(vy) < 0.01) {
vx = 0.0;
vy = 0.0;
released = false;
}
}
}
Elastic Motion 3
int n = 7;
int selected;
Spring [] s = new Spring[n];
void setup() {
size(300, 300);
for (int i = 0; i < n; i++) {
s[i] = new Spring();
s[i].xpos += 30*(i+1);
s[i].ypos = 50;
}
}
void draw() {
background(200, 10);
for (int i=0; i< n; i++) {
if (s[i].released)
s[i].move();
ellipse(s[i].xpos, s[i].ypos, 10, 10);
}
for (int i = 0; i < n; i++)
line(s[i].xpos, s[i].ypos, s[i].xpos, height-50);
}
void mouseMoved() {
for (int i = 0; i < n; i++)
if (dist(mouseX, mouseY, s[i].xpos, s[i].ypos) < 10 && s[i].released == false) {
//s[i].xpos = random(width);
s[i].ypos = random(height);
println("i = " + i);
selected = i;
s[selected].released = true;
}
}
2D Moving with Friction
class Circle {
int d ;
float x, y, sx, sy, f = 0.5;
Circle(int d) {
this.d = d;
x = random(width);
y = random(height);
sx = random(1);
sy = random(1);
}
void move() {
x += sx/f;
y += sy/f;
if (x < 0 || x > width) sx *= -1;
if (y < 0 || y > height) sy *= -1;
x = constrain(x, 0, width);
y = constrain(y, 0, height);
ellipse(int(x), int(y), d, d);
f += 0.01;
}
}
Circle c;
void setup() {
size(600, 400);
fill(0);
c = new Circle(30);
}
void draw() {
background(255);
c.move();
}
void mouseDragged() {
if (dist(mouseX, mouseY, c.x, c.y) < 20) {
c.f = 0.5;
c.sx = mouseX - pmouseX;
c.sy = mouseY - pmouseY;
}
}
Circle Array
// using the previous Circle class
int n = 10;
Circle c[] = new Circle[n];
void setup() {
size(600, 400);
noStroke();
fill(0) ;
for (int i = 0; i < n; i++)
c[i] = new Circle(5*(i+1));
}
void draw() {
background(255);
for (int i = 0; i < n; i++)
c[i].move();
}
void mouseDragged() {
for (int i = 0; i < n; i++)
if (dist(mouseX, mouseY, c[i].x, c[i].y) < 20) {
c[i].f = 0.5;
c[i].sx = mouseX - pmouseX;
c[i].sy = mouseY - pmouseY;
}
}
atan2(y , x)
Rotate rectangle
void draw() {
background(204);
translate(width/2, height/2);
float a = atan2(mouseY-height/2, mouseX-width/2);
rotate(a);
rect(-30, -5, 60, 10);
}
Collision
class Circle {
int id, d = 30;
float x, y, sx, sy, f = 0.5;
Circle ca[];
Circle(int id, Circle ca[]) {
this.id = id;
x = random(width);
y = random(height);
sx = random(1);
sy = random(1);
this.ca = ca;
}
void move() {
x += sx/f;
y += sy/f;
if (x < 0 || x > width) sx *= -1;
if (y < 0 || y > height) sy *= -1;
x = constrain(x, 0, width);
y = constrain(y, 0, height);
ellipse(int(x), int(y), d, d);
f += 0.01;
}
}
Collision (cont.)
void collide() {
for(int i = 0; i < ca.length; i++) {
if (i != id && dist(x, y, ca[i].x, ca[i].y) < d) {
float a = atan2(ca[i].y - y, ca[i].x - x);
float ax = x + cos(a)*d - ca[i].x;
float ay = y + sin(a)*d - ca[i].y;
sx -= ax;
sy -= ay;
ca[i].sx += ax;
ca[i].sy += ay;
}
}
}
}
int n = 10;
Circle c[] = new Circle[n];
void setup() {
size(600, 400);
fill(0);
for (int i = 0; i < n; i++)
c[i] = new Circle(i, c);
}
void draw() {
background(255);
for (int i = 0; i < n; i++) {
c[i].collide();
c[i].move();
}
}
void mouseDragged() {
for (int i = 0; i < n; i++)
if (dist(mouseX, mouseY, c[i].x, c[i].y) < 20) {
c[i].f = 0.5;
c[i].sx = mouseX - pmouseX;
c[i].sy = mouseY - pmouseY;
}
}