差分
このページの2つのバージョン間の差分を表示します。
両方とも前のリビジョン 前のリビジョン 次のリビジョン | 前のリビジョン 次のリビジョン両方とも次のリビジョン | ||
lecture:design_with_prototyping:p5.js編:13.動きの再構成 [2021/05/13 02:10] – [物理演算] baba | lecture:design_with_prototyping:p5.js編:13.動きの再構成 [2021/05/25 13:09] – [パーティクル] baba | ||
---|---|---|---|
行 12: | 行 12: | ||
特段面白いものではないと思いますが、次のようなコードはどうでしょうか?p5jsのエディタごとこのページにはります。短いプログラムですが、じっくり読んでみましょう。単純にマウス位置に丸を描くのではなく、マウスカーソルの位置に徐々に丸が近づいていくプログラムにしています。 | 特段面白いものではないと思いますが、次のようなコードはどうでしょうか?p5jsのエディタごとこのページにはります。短いプログラムですが、じっくり読んでみましょう。単純にマウス位置に丸を描くのではなく、マウスカーソルの位置に徐々に丸が近づいていくプログラムにしています。 | ||
- | <html> | + | |
- | <iframe src="https://editor.p5js.org/tetsuakibaba/sketches/lq6TI8Sis" | + | <WRAP group> |
- | </html> | + | <WRAP half column> |
+ | < | ||
+ | function setup() { | ||
+ | createCanvas(displayWidth, | ||
+ | } | ||
+ | |||
+ | var position | ||
+ | x: 0, | ||
+ | y: 0 | ||
+ | }; | ||
+ | |||
+ | function draw() { | ||
+ | background(100); | ||
+ | circle(position.x, | ||
+ | |||
+ | position.x = position.x + (mouseX - position.x) | ||
+ | position.y = position.y + (mouseY - position.y) | ||
+ | } | ||
+ | </file> | ||
+ | </WRAP> | ||
+ | |||
+ | <WRAP half column> | ||
+ | {{: | ||
+ | </WRAP> | ||
+ | </WRAP> | ||
これらプログラムはどちらもマウスカーソルにくっつくプログラムであり、目的は達成しています。一方で操作して「気持ちいい」、「楽しい」と感じるのはどちらでしょうか? 状況にもよるかもしれませんが、おそらく後者の方が気持ちいい、楽しいと思う人が多いのではないでしょうか?ただ動く、といってもその動きは様々です。まっすぐ移動する円であっても、徐々に早くなって、最後はゆっくり止まるといったある種の無駄な動作が、私達人間にとっては体験の楽しさや興味、注意を引く大きな仕掛けになっていることがあります。これは映像制作に限らずインタラクションでも同じことが言えます。 | これらプログラムはどちらもマウスカーソルにくっつくプログラムであり、目的は達成しています。一方で操作して「気持ちいい」、「楽しい」と感じるのはどちらでしょうか? 状況にもよるかもしれませんが、おそらく後者の方が気持ちいい、楽しいと思う人が多いのではないでしょうか?ただ動く、といってもその動きは様々です。まっすぐ移動する円であっても、徐々に早くなって、最後はゆっくり止まるといったある種の無駄な動作が、私達人間にとっては体験の楽しさや興味、注意を引く大きな仕掛けになっていることがあります。これは映像制作に限らずインタラクションでも同じことが言えます。 | ||
行 34: | 行 59: | ||
加速度は一秒間で増加する速度のことです.つまり時間が経過するほどどんどん速度が早くなっていきます.例えば以下のようなコードを書いてみます. | 加速度は一秒間で増加する速度のことです.つまり時間が経過するほどどんどん速度が早くなっていきます.例えば以下のようなコードを書いてみます. | ||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
< | < | ||
var ball = { | var ball = { | ||
行 66: | 行 93: | ||
} | } | ||
</ | </ | ||
+ | |||
+ | </ | ||
+ | |||
+ | <WRAP half column> | ||
+ | {{: | ||
+ | </ | ||
+ | </ | ||
+ | |||
非常にシンプルな計算ですが,物理法則に基づいた計算を行っています.下方向に重力が生じていると考え,フレーム更新毎に下方向の速度を0.1ずつ増やしているだけです.結果としてボールが自由に落下しているように感じられると思います. | 非常にシンプルな計算ですが,物理法則に基づいた計算を行っています.下方向に重力が生じていると考え,フレーム更新毎に下方向の速度を0.1ずつ増やしているだけです.結果としてボールが自由に落下しているように感じられると思います. | ||
+ | |||
+ | では次は地面にぶつかったときに跳ね返らせてみます.高校物理習ったとおりですが,衝突したときにはその衝突した瞬間の速度と逆向きの速度になります.ただし同じ速度だと永遠とはね続けるので跳ね返り係数(k)を0.5などとして計算します. | ||
+ | |||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
+ | |||
+ | < | ||
+ | var ball = { | ||
+ | x:0, | ||
+ | y:0, | ||
+ | v: { | ||
+ | x:0.0, | ||
+ | y:0.0 | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | function setup() { | ||
+ | createCanvas(400, | ||
+ | } | ||
+ | |||
+ | function draw() { | ||
+ | background(220); | ||
+ | | ||
+ | ball.x += ball.v.x; | ||
+ | ball.y += ball.v.y; | ||
+ | if( ball.y > 400-5 ){ | ||
+ | ball.v.y = 0.5*(-ball.v.y); | ||
+ | ball.y = 400-5; | ||
+ | } | ||
+ | circle(ball.x, | ||
+ | ball.v.y += 0.1; | ||
+ | } | ||
+ | |||
+ | function mousePressed() | ||
+ | { | ||
+ | ball.x = mouseX; | ||
+ | ball.y = mouseY; | ||
+ | ball.v.x = 0; | ||
+ | ball.v.y = 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | </ | ||
+ | |||
+ | <WRAP half column> | ||
+ | {{: | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | |||
+ | 実行結果を確認するとたしかにボールが跳ねているように見えますね. 重力加速度を0.1としていますが,この値を変えることでボールの動きがどのように変化するかをよく観察してください.この0.1は重力加速度なので,この値が増えるということは,より重力が強い世界の場合となっています.なんだか重そうに見えませんか?落下の仕方,跳ね返り方で私達人間はその物体に対する印象が変わってしまいます. | ||
+ | |||
+ | <WRAP center round todo 60%> | ||
+ | ここまでのコードを参考にして,html上で重量加速度を自由に設定できるスライダーを用意し,重力加速度を操作することで画面内のボールを落としたり,浮かび上がらせたりする操作を実現してみましょう. | ||
+ | </ | ||
+ | |||
+ | さらに物理演算を利用したアプリケーションを作成したい場合はライブラリを利用すると良いでしょう.詳しくはThe Coding Trainで学習してみましょう. | ||
+ | * https:// | ||
+ | * テキストと組み合わせるとこんなこともできます:https:// | ||
+ | |||
+ | ===== 物理法則に従わなくたってよい ===== | ||
+ | 物理演算で遊ぶととっても楽しいのですが,私達がデザインしているのは現実世界だけでなく,デジタル世界だからこそ成立するものでも良いわけです.例えばアニメーションの世界では,キャラクターの動きを完全に物理法則に基づいて描いてしまうと,アニメーションの面白みがなくなり,単調なアニメーションになってしまいます.例えばキャラクターが高く飛び上がるときも,通常よりもしゃがみ込みから飛び上がる瞬間までの時間を長くとることで,アニメーションとしてのジャンプを強調(誇張)することができます. | ||
+ | |||
+ | 上記で記述した自由落下のアルゴリズムを少し変更し,落ち始めの瞬間は一瞬止まったようにみえるが,ちょっと時間が立つと「ストン!」と落ちるようなアニメーションに記述し直してみましょう.ニュートン力学ではなく,トムとジェリー力学ですね(https:// | ||
+ | |||
+ | |||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
+ | ボールにかかる重力加速度を $a$,ボールの下方向の速度を$V$としたとき | ||
+ | |||
+ | \[ | ||
+ | a = \begin{cases} | ||
+ | 1.0 & V > 0.2 \\ | ||
+ | 0.01 & V \leqq 0.2 | ||
+ | \end{cases} | ||
+ | \] | ||
+ | |||
+ | として,プログラムを記述すると右図のようなアニメーションに変わります.ボールが下に落ちる速度がある一定の大きさになると,加速度が大きくなり,速度が落ちるとまた加速度が小さくなります.結果として,「落下する」というアニメーションを物理法則にとらわれずに記述することができました. | ||
+ | </ | ||
+ | |||
+ | <WRAP half column> | ||
+ | {{: | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <WRAP center round todo 60%> | ||
+ | 以上の内容を踏まえて, | ||
+ | * 軽いボール | ||
+ | * 重いボール | ||
+ | をそれぞれ物理法則を変えてもいいので,自分なりに表現してみましょう. | ||
+ | </ | ||
+ | |||
+ | |||
+ | ===== パーティクル ===== | ||
+ | この動きを一つだけで表現するのではなく、たくさんのオブジェクトに対して共通の動きを適応した代表的な手法にパーティクルがあります。これまでのサンプルを利用して、複数のボールを作成してみます。 | ||
+ | |||
+ | <WRAP group> | ||
+ | <WRAP half column> | ||
+ | < | ||
+ | // ボールをたくさん作るので配列で宣言する | ||
+ | var balls = []; | ||
+ | |||
+ | function setup() { | ||
+ | createCanvas(400, | ||
+ | | ||
+ | // ボールの個数を100個にして、ballsの配列に連想配列を初期化して追加する | ||
+ | for (let i = 0; i < 100; i++) { | ||
+ | balls.push({ | ||
+ | x: random(width), | ||
+ | y: random(height), | ||
+ | v: { | ||
+ | x: 0.0, | ||
+ | y: 0.0, | ||
+ | }, | ||
+ | }); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | function draw() { | ||
+ | background(220); | ||
+ | |||
+ | // ボールの個数分の描画処理 | ||
+ | for (const ball of balls) { | ||
+ | let g = 1.0; | ||
+ | ball.x += ball.v.x; | ||
+ | ball.y += ball.v.y; | ||
+ | if (ball.y > 400 - 5) { | ||
+ | ball.v.y = 0.5 * -ball.v.y; | ||
+ | ball.y = 400 - 5; | ||
+ | } | ||
+ | ball.v.y += g; | ||
+ | |||
+ | noStroke(); | ||
+ | fill(0); | ||
+ | circle(ball.x, | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | <WRAP half column> | ||
+ | {{: | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | 同じプログラムでもそれがたくさんになると、印象が変わりますね。では次は重力の無い世界のプログラムに変更してみます。ただし重力がないとただそこにとどまるだけのボールになってしまうため、初速度を設定しておきます。初速度はそのボールに設定する最初の速度です。また飛んでいってそのまま見えなくなってしまうとつまらないので、一定期間飛び続けたら自動的に最初に戻るようにします。パーティクルではこのことをライフと読んでおり、パーティクル(粒子)が発生してからなくなるまでの寿命のことを意味します。 | ||
+ | |||
+ | |||
+ |