人工言語入門 A 2010
Processingによる高度なモーション:バネの動きを作る
今日の内容
- 高度なアニメーション表現を身につける
- 物理法則を用いたアニメーションの表現
- ばね
- 万有引力
「ばね」を定義する
「ばね」を数学的に定義する
- 「ばね」を数学的に定義する
- フックの法則
- バネの伸びが x のとき、それによって生じる力を F とすると
- F = -kx ( k:ばね定数)
- フックの定理は以下のように書き直すことができる
- springForce = -stiffness * stretch
- バネの力 = -バネの硬さ x バネの伸び
- さらに「バネの伸び」の部分を解釈する
- springForce = -stiffness * (position – restPosition)
- バネの力 = -バネの硬さ x (現在位置 – ばねの静止位置)
- 式を整理
- springForce = stiffness * (restPositon – position)
- バネの力 = バネの硬さ x (静止位置 – 現在位置)
- この時、ばねの移動速度は下記のように表現される
- velocity = friction * (velocity + springFroce)
- 速度 = 摩擦 * (速度 + バネの力)
- この式を利用して、簡単なアニメーションをProcessingで作成してみる
ばね1:シンプルな「ばね」
- 「ばね」の公式(フックの法則)を利用して、シンプルな「ばね」の動きをプログラミングしてみる
float stiffness = 0.1; //ばねの強度
float damping = 0.9; //摩擦
float velocity = 0.0; //速度
float targetY; //目標位置
float y; //現在位置
void setup() {
size(400, 400);
noStroke();
}
void draw() {
fill(0, 12);
rect(0, 0, width, height);
fill(255);
float force = stiffness * (targetY - y); //フックの法則 f = -kx
velocity = damping * (velocity + force); //速度を計算
y += velocity; //速度分を座標に
rect(10, y, width - 20, 10); //四角を描画
targetY = mouseY; //マウスのY座標を目標位置に
}
ばね2:重さ(mass)を付加
- もうひとつの要素を付加する – バネに付いている物体の重さ(mass)
- 重さと力の関係はニュートンの運動の第二法則から導きだされる
- F = ma
- F:力、m:質量、a:加速度
- 式を変換
- a = F / m
- これを「ばね」にあてはめると、下記のように解釈できる
- acceleration = springForce / mass
- 加速 = バネの力 / 重さ
- 先程のプログラムに重さの要素を付加する
- 重さの概念を追加した「ばね」
//2つの重さの異なる物体で、ばね運動を作成
float y1, y2; //現在位置
float velocity1, velocity2; //速度
float mass1 = 1.0; //物体1の重さ
float mass2 = 6.0; //物体2の重さ
float stiffness = 0.1; //バネの剛性
float damping = 0.9; //摩擦係数
void setup() {
size(400, 400);
noStroke();
}
void draw() {
fill(0, 12);
rect(0, 0, width, height);
fill(255);
float targetY = mouseY; //目標位置
//物体1
float forceA = stiffness * (targetY - y1); //フックの法則
float accelerationY1 = forceA / mass1; //重さから加速度を算出
velocity1 = damping * (velocity1 + accelerationY1); //加速度を加味して速度を計算
y1 += velocity1; //位置を算出
rect(0, y1, width/2, 15);
//物体2
float forceB = stiffness * (targetY - y2); //フックの法則
float accelerationY2 = forceB / mass2; //重さから加速度を算出
velocity2 = damping * (velocity2 + accelerationY2);//加速度を加味して速度を計算
y2 += velocity2; //位置を算出
rect(width/2, y2, width/2, 15);
}
ばね3:2次元座標に展開、重力を付加
- Y軸方向だけでなくX軸方向にも動けるように
- 重力(gravity)の要素も付加
- 常に一定の力をY軸方向に付加する
float stiffness = 0.05;
float damping = 0.9;
float mass = 3.0;
float gravity = 0.0;
float velocityX = 0.0, velocityY = 0.0;
float targetX, targetY;
float x, y;
void setup() {
size(600, 600);
smooth();
}
void draw() {
background(0);
float forceX = stiffness * (targetX - x);
float accelerationX = forceX / mass;
velocityX = damping * (velocityX + accelerationX);
x += velocityX;
float forceY = stiffness * (targetY - y);
forceY += gravity;
float accelerationY = forceY / mass;
velocityY = damping * (velocityY + accelerationY);
y += velocityY;
noStroke();
fill(255);
ellipse(x, y, 40, 40);
stroke(127);
noFill();
line(mouseX, mouseY, x, y);
targetX = mouseX;
targetY = mouseY;
}
ばね4:「ばね」をクラスとして定義する
- ばねの動きを汎用的に使えるようにクラスとして定義する
- Spring2Dクラス
- メインプログラム
//Spring2Dクラスを利用して、ばねの動きを生成
Spring2D s1, s2;
float gravity = 15.0;
float mass = 2.0;
void setup() {
size(400, 400);
smooth();
fill(0);
//入力:x座標, y座標, 摩擦, 重力
s1 = new Spring2D(0.0, width / 2, mass, gravity);
s2 = new Spring2D(0.0, width / 2, mass, gravity);
}
void draw() {
background(204);
s1.update(mouseX, mouseY);
s1.display(mouseX, mouseY);
s2.update(s1.x, s1.y);
s2.display(s1.x, s1.y);
}
- 「ばね」を定義するクラス:Spring2D
class Spring2D {
float vx, vy;
float x, y;
float gravity;
float mass;
float radius = 10;
float stiffness = 0.2;
float damping = 0.7;
//コンストラクタ
Spring2D(float xpos, float ypos, float m, float g) {
x = xpos;
y = ypos;
mass = m;
gravity = g;
}
//位置を計算
void update(float targetX, float targetY) {
float forceX = (targetX - x) * stiffness;
float ax = forceX / mass;
vx = damping * (vx + ax);
x += vx;
float forceY = (targetY - y) * stiffness;
forceY += gravity;
float ay = forceY / mass;
vy = damping * (vy + ay);
y += vy;
}
//表示
void display(float nx, float ny) {
noStroke();
ellipse(x, y, radius*2, radius*2);
stroke(255);
line(x, y, nx, ny);
}
}
ばね5:ばねを数珠繋ぎにしてみる
- Spring2Dクラスで定義した「ばね」を直列に繋いでいく
int numSprings = 10;
Spring2D[] s = new Spring2D[numSprings];
float gravity = 5.0;
float mass = 5.0;
float stiffness = 0.2;
float damping = 0.8;
void setup() {
size(600, 600);
smooth();
fill(0);
for (int i = 0; i < numSprings; i++) {
s[i] = new Spring2D(width / 2, i*(height / numSprings), mass, gravity, stiffness, damping);
}
}
void draw() {
background(204);
s[0].update(mouseX, mouseY);
s[0].display(mouseX, mouseY);
for (int i = 1; i < numSprings; i++) {
s[i].update(s[i-1].x, s[i-1].y);
s[i].display(s[i-1].x, s[i-1].y);
}
}






