見出し画像

無限の動きを有限の時間に閉じ込める

個別のアイテムがヒラヒラしながら中央に向けて無限に吸い込まれていくこの動画、一番外側のヒラヒラは 120秒ぐらいで吸い込まれて消えていきます。

でも、これ全体で 6秒の動画なんです。結構簡単な仕掛けでこのような無限運動を作ることが出来ます。

画像1

この記事は全文無料でお読みいただけます。もしお気に召しましたら投げ銭お願いしますね。😉✨

画像2

短い動画で無限運動に見せる仕掛け

先程の動画は Twitter 上で繰返し再生(ループ再生)されます。
Twitter のヘルプによると『60秒以下の動画はすべて自動的にループ再生される』そうです。

これ、以前は 60秒じゃなくて 6.5秒までだったんですよね。その頃の名残で 6秒のループ動画にしています。

20秒でも 60秒でも同じ考えで無限ループ動画は作れるんですが、長いとあまり見てもらえないみたいで、 6秒ぐらいがちょうどいいのかもしれません。

ループ再生で無限ループのように見せる仕掛けは単純。開始と終了の絵を繫げるというだけです。

例えばこれは 12個の円が永遠に回転しつづける 3秒の動画です。開始と終了の円の位置がほぼ同じでしょう?

note 上だとループしないのでどう作られた動画なのかわかりやすいですね。
ループさせたい場合は Twitter で開いてみてください。

回転だから 360度一周させればもちろん無限ループになるんですが、動きが激しいと Twitter で画質が潰れてしまったりするし、なによりトリックが無いとなんか物足りないでしょ?😉

この例の場合一個隣の円まで 360度 / 12個 = 30度 だけ動かしています。
全部同じ形、色なので、隣に移動させるだけで永久に回転してるように見せることができるというわけです。

画像3

アイテムの形を変えるには?

先程の例のアイテムで、形と色を変化させながら無限ループのように見せることもできます。

この場合も「開始と終了の絵を繫げる」という考えは同じです。
例えば 丸 → 四角 → 三角 と並んでいる場合、丸を移動させながら四角の位置に来た時に四角に、四角は三角の位置に移動したときに三角にすればよいのです。つまり、位置によって形を決めればいいわけです。

……。
よくわかんないので実際に見てみましょう。丸、四角、三角の代わりに変化量がわかりやすい弓形 arc() を使ってみます。

/**
* 無限の動きを有限の時間に閉じ込める
* 
* @author @deconbatch
* @version 0.1
* @license GPL Version 3 http://www.gnu.org/licenses/
* Processing 3.5.3
* 2020.09.20
*/

int frameMax = 24 * 6; // 24fps x 6秒
int itemMax  = 12;     // アイテム数

void setup() {
 size(720, 720);
 colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
}

void draw() {

 float frameRatio = map(frameCount, 1, frameMax, 0.0, 1.0);
 
 background(0.0, 0.0, 90.0, 100.0);
 translate(width * 0.5, height * 0.5);
 stroke(0.0, 0.0, 30.0, 100.0);

 // 円周上にアイテムを描画
 for (float theta = 0.0; theta < TWO_PI; theta += TWO_PI / itemMax) {

   // 動画の終わりまでに隣のアイテムまで移動
   float shifting = frameRatio * TWO_PI / itemMax;
   float x = width * 0.35 * cos(theta - shifting);
   float y = width * 0.35 * sin(theta - shifting);

   // アイテム描画
   drawItem(x, y);
​
 }
 
 // 24fps x 6秒分の画像生成したら終了
 saveFrame("frames/" + String.format("%04d", frameCount) + ".png");
 if (frameCount > frameMax) {
   exit();
 }
 
}

/* drawItem : 描画開始座標で形が決まるアイテムを描画(パックマン)
* x, y : 描画開始座標
*/
void drawItem(float x, float y) {

 float iSize = 80.0;
 float theta = PI - atan2(y, x);

 stroke(0.0, 0.0, 0.0, 100.0);
 strokeWeight(2.0);

 pushMatrix();
 translate(x, y);
 rotate(theta);
 fill((360.0 + theta * 240.0) % 360.0, 40.0, 80.0, 100.0);
 arc(0.0, 0.0, iSize, iSize, 0.0, theta, PIE);
 fill(0.0, 0.0, 90.0, 100.0);
 ellipse(iSize * 0.3, iSize * 0.2, iSize * 0.1, iSize * 0.1);
 popMatrix();

}

この例ではキャンバスの中央から見たアイテム位置の角度によって形を決めています。
これにより、隣のアイテム位置に移動したときにはそこのアイテムと同じ形になるというわけです。

2次元ノイズを使って xy座標によって形を決めるという方法もあります。

/* drawItem : 描画開始座標で形が決まるアイテムを描画(意味のない形)
* x, y : 描画開始座標

void drawItem(float x, float y) {
 int   stepMax = 20;
 float stepDiv = 12.0;
 float nStep   = 0.005;
 float nParam  = noise(width + x * nStep, height + y * nStep);

 stroke(0.0, 0.0, 0.0, 100.0);
 strokeWeight(2.0);
 fill(nParam * 360.0, 40.0, 80.0, 100.0);
 beginShape();
 for (int stepCnt = 0; stepCnt < stepMax; stepCnt++) {
   float theta = TWO_PI * floor(12.0 * noise(nParam, stepCnt)) / 4.0;
   x += stepDiv * cos(theta);
   y += stepDiv * sin(theta);
   vertex(x, y);
 }
 endShape();
}

今回のコード例では円運動でしたが、螺旋でも蛇行でも同じ考えで無限運動を作ることが出来ます。
いろんなアイデアで面白い動画が作れると思うので、ぜひ何か作ってみてください。🙂

画像4

参考

周期運動を使った無限ループアニメーションの作り方。

2次元ノイズを使って xy座標によって形を決めるという方法のヒント。


画像5

📘 他にも note でいろんな記事書いています。

🐦 Twitter でもいろいろ面白いの上げてるのでぜひフォローしてください。

🎨 こちらのブログはソースコード付きの作品集になってます。


ここでこの記事はおしまいです。もしこの記事がお気に召しましたら投げ銭お願いします。😉✨

ここから先は

0字

¥ 100

この記事が面白かったらサポートしていただけませんか? ぜんざい好きな私に、ぜんざいをお腹いっぱい食べさせてほしい。あなたのことを想いながら食べるから、ぜんざいサポートお願いね 💕