「速度」の解説の前に、簡単なスケッチを作成してみましょう。キャンバスの中央を、左から右方向に移動させてみてください。動かす量は draw()
ブロック1回ごとに 5
px程度、画面の右端に達したら左端に戻します。
(→vel_init
)
「速度」とは、一定時間でどのくらい位置が変わるかを表すものです。例えば「車の速度が60km/h」とは、車の位置が1時間で60km進むという状態です。
先の練習では、 draw()
ブロックが1回実行されるごとに5px移動していました。 draw()
1回分を1フレームと呼ぶとき、エージェントの速度は「5px/フレーム」ですね。
先ほど作成したスケッチを、速度を意識した書きかたに直してみましょう。速度も変数として宣言して、全体を書き換えてみてください。
(→vel_hello
)
…
// エージェントの速度
float vx;
float vy;
void setup() {
…
// 初速を設定
vx = 5;
vy = 0;
}
void draw() {
// 速度を位置に反映
x += vx;
y += vy;
…
}
これで前と同じ動きになりました。が、わざわざ速度を変数に入れる手間をかけることで、何かよいことがあるのでしょうか?
このままスケッチを改造して、左右の矢印キーによって速度を上げたり下げたりできるようにしてみましょう。キーを押したときに実行されるのは keyPressed()
ブロックでしたね。
(→vel_key
)
// キーを押したときに実行されるブロック
void keyPressed() {
// 左右矢印キーで速度を変化させる
if (keyCode == LEFT) {
vx -= 0.5;
}
else if (keyCode == RIGHT) {
vx += 0.5;
}
}
速度を変数に入れて覚えておくことで、速度を維持したまま少しずつ変化させることもできるようになりました。
画面端を壁と見立てて跳ね返らせてみましょう。
「跳ね返る」とはどういう現象でしょうか?例えば右側の壁に速度 5
でぶつかった結果、方向が反転して -5
になるのが跳ね返りです。
コードで書くとこんな感じ。 -1
をかけて方向を反転させるのがポイントです。
// 右端に達したら、速度を反転させる
if (x > width) {
vx *= -1;
}
このままの他の壁の判定処理も書いてみてください。右端のif文とほとんど同じ形になりますね。
さて、現実世界において、跳ね返ったものがそのままの速度で返ってくることはまずありません。エネルギーの損失が発生して、速度は前より小さくなるのが自然です。
この現象をスケッチでどう再現すればよいかというと、 vx
に掛け算している数値1( -1
)をもう少し小さい数値にしてあげましょう。例えば -0.5
にすると、跳ね返り後の速度の大きさは半分になります。
(→vel_bounce
)
以前作ったランダムウォークでは、位置をランダムに変化させていました。
(→random_walk
)
このスケッチに速度の概念を取り入れて、位置ではなく速度をランダムに変化させるようにしてみましょう。
…
// 速度を位置に反映
x += vx;
y += vy;
// 速度をランダムに変化させる
vx += random(-0.2, +0.2);
vy += random(-0.2, +0.2);
…
動きの印象がだいぶ変わりましたね。速度がある程度保たれるので、ジグザグする不自然さが消えて滑らかに漂うようになりました。
(→vel_random_walk
)
先の例では、速度を上げるとすぐに画面外に滑っていってしまいます。(見やすいように軌跡を残してみました)
現実世界の運動では、空気抵抗(空気との摩擦)や接地面との摩擦によってエネルギーの損失が生じて少しずつ減速するのですが、これがないと速度がつきすぎてしまうのです。
この問題を解決するには、毎フレームごとに強制的に速度を小さくしていくのがもっとも簡単です。 draw()
ブロック内で、速度の変数に1より小さな数を掛けてあげましょう。
// 簡易的な空気抵抗を加える
// (自然に減速=毎フレーム速度を小さくする)
vx *= 0.99;
vy *= 0.99;
適度に減速され、動きに味が出てきましたね。考えてみれば、手描きの線も物理法則のもとで手が動いて生み出されているわけです。より自然な動きに感じられるのも納得感があります。
これほどシンプルなランダムウォークにも、「速度に加える変化」「減速用の数値」など、パラメーターがしっかり含まれています。これらを調整するだけでも多様な動きを生み出せます。動きのバリエーションを3つ以上作ってみましょう。
「加速度」とは、一定時間でどのくらい速度が変わるかを表すものです。速度の速度、のようなものですね。例えば「車の加速度が30km/h2」とは、車の速度が1時間で30km/h大きくなるという状態です。
エージェントが右に移動するスケッチを改造して、だんだん加速するようにしてみましょう。速度 vx
がだんだん大きくなるように書けばよいので…。
…
// 加速する(=速度を上げる)
vx += 0.05;
// 速度を位置に反映
x += vx;
…
こんな感じです。加速度が速度を、速度が位置を更新しているのがポイントです。
(→acc_hello
)
われわれがふだん感じている重力。実はこれ「重力加速度」といって、加速度の一種なのです。下方向の加速度を加えて、重力を再現してみましょう。すぐに画面外に消えてしまうので、「跳ね返り」の項を参考に床を設けてあげてください。
(→acc_gravity
)
このままスケッチを改造して、クリックしたときにランダムな方向に弾け飛ぶようにしてみましょう。
mousePressed()
ブロックで、速度にランダムな数値を加えれば実現できそうです。
(→acc_flick
)
void mousePressed() {
// ランダムな方向の速度を与える
vx += random(-10, 10);
vy += random(-5, 5);
}
この例においても、エネルギーの損失がないためボールが滑っているように見えてしまいますね。
速度のところでやったのと同様に、 draw()
ブロック内で速度に1より小さな数を掛けてあげましょう。
(→acc_flick_friction
)
だいぶ自然な動きになりましたね。
acc_grab
)acc_grab_throw
)mag(0, 0, vx, vy)
で計算できます)既存のスケッチに速度・加速度を導入して、自然な動きを加えてみましょう。
「配列」で作った複数体のランダムウォークに組み込めば、これまでできなかった模様を描けますし、重力を組み込めばさらに花火のような表現も可能になります。
(→vel_random_walk_array
)
ペンのスケッチと組み合わせれば、エージェントが勝手気ままに線を描くスケッチを作ることもできますね。
速度にかける数値は「反発係数」「跳ね返り係数」と呼ばれ、 1
の場合はエネルギー損失のない「完全弾性衝突」になります ↩︎