《プログラマーが徹底解説!》AeエクスプレッションTIPS #13 反射

今回から、Xで投稿している「すぐに使えるエクスプレッションTIPS」の解説をしていきたいと思います。

(いきなり#13から始まっていますが初回です)

Xで反響が大きかったものを中心に、順不同だったり、過去に遡ったり、間が空いたり色々すると思いますので、その辺は気にせずご覧ください。

はじめに

・CS6/CC両対応のため、ECMAScript3相当のJavascript(ExtendScript)で記載しています。
・コンポジションサイズは、1920 * 1080 です。

では、解説を始めていきます!

1. 反射エクスプレッション

まずは、このポストの動画を再生してみてください。赤い球体が黄色い点線を境に、反射するような動作になっていますね?

今回は、この「反射」アニメーションが、どのような仕組みで動作しているのかについて、1つずつ説明していきたいと思います。

補足説明

・変数pは、位置=positionの頭文字、変数rは、反射境界線=reflective borderの頭文字という想定で名前を付けてあります

エクスプレッション解説

これから説明するエクスプレッションは以下です。

var p = wiggle(0.5, 500);
var r = 960;
[(p[0] < r) ? p[0] : r - (p[0] - r), p[1]];

これを、位置プロパティにコピペするだけで、反射するような動作になります。

登場人物

まず最初は、登場人物から見ていきたいと思います。

右から、

  • 反射前位置(p)・・・wiggleが適用された反射前の位置
  • 反射境界線(r)・・・反射する境界線。この境界線より右に移動すると反射します
  • 反射後位置・・・反射境界線で反射した後の位置

となります。この3人の登場人物がよくわからなくなってしまったら、この画像をもう一度見に戻ってきてください。

それでは、その仕組みを一行ずつ分解して見ていきましょう!

ますは1行目から。

1行目

var p = wiggle(0.5, 500);

最初に、変数pにwiggleの結果を代入しています。位置プロパティのwiggleの結果は、要素数2の配列(X位置とY位置)なので、pも要素数2の配列となります。

また、wiggleの具体的な値は、初期値のままであれば、[960, 540]を中心に、上下左右500pxの範囲の値で、2秒に1回変動します。

これが、1人目の登場人物「反射前位置(p)」になります。

次は2行目。

2行目

var r = 960;

変数r には、960 を入れました。

これが、2人目の登場人物「反射境界線(r)」になります。960 は1920の半分なので、画面の中央が反射境界線になりました。

最後は3行目。

3行目

[(p[0] < r) ? p[0] : r - (p[0] - r), p[1]];

まず、大前提として、エクスプレッションは、最後に書いた値がプロパティに反映されます。

今回は位置プロパティなので、要素数2の配列の形式で書き込むので、以下の形式になっています。

[/* X位置の値 */, /* Y位置の値 */];

それでは、更に分解して、X位置の値の部分からみていきましょう!

補足説明

・「変数」は、数値や、文字や、配列など様々なデータを入れる入れ物のことです

・「配列」は、複数のデータが入る入れ物のことです。入っている値の数を「要素数」といいます。

・「配列」が入っている「変数p」から最初の値を取り出す場合は p[0]、2つ目の値を取り出す場合は p[1] と記載します。

位置プロパティのX値に設定する値

3行目

[(p[0] < r) ? p[0] : r - (p[0] - r), p[1]];

から、「X位置の値」だけを抜き出すと、以下のようになります。

(p[0] < r) ? p[0] : r - (p[0] - r)

これは、Javascriptの「条件式」を短縮した、「条件 (三項) 演算子」という構文です。

書き方は、「もしも、~だったら、~を実行。違ければ、~を実行」というように、条件と、実行内容をセットにして記述します。

(/*条件*/) ? /*条件が成立したら実行する内容*/ : /*条件が成立しなかったら実行する内容*/

ちなみに、「条件式」について詳しく知りたい方は、以下の記事にまとめてあるのでご覧ください。

「条件 (三項) 演算子」の部分を説明するために、元の「条件式」に書き換えると以下になります。

if(p[0] < r) {
    p[0];
} else {
    r - (p[0] - r);
}

元の「条件 (三項) 演算子」と見比べてみてください。よく見ると、書き方が変わっただけで、条件など、書いてあることが同じなのがわかりますか?

実際にどんなことをしているのか、まずはこの「条件式」に、コメントで説明を追加してみます。

if(p[0] < r) {
    // もしも、p[0](反射前X位置)が、r(反射境界線)未満だったら = 反射境界線より左だったら
    p[0]; // 反射前X位置をそのまま使用
} else {
    // それ以外だったら = 反射境界線より右だったら
    r - (p[0] - r); // 反射後位置を計算
}

上記コメントにも書いてありますが、改めて図にまとめてみました。

上記画像のように、反射前X位置(p[0])が、反射境界線(r)よりも左にあった場合は、反射前X位置をそのまま利用します。

また、反射境界線よりも右にあったら、反射後X位置を計算するという条件式になっています。

反射X位置の計算

では、ここからが本題です。「って、まだ本題じゃなかったの?!」と思われた方、すみません。

この先が、このエクスプレッションの本当の重要な部分なんです。あと少しです!

ここでも説明用の画像を用意したので、この画像を見ながら説明していきます。

それでは、最初に紹介した登場人物「反射前位置(p)」「反射境界線(r)」を使って、「反射後位置」を計算していきましょう!

まず、反射境界線をどれくらい超えているのかが知りたいので、青い部分を計算します。

この青い部分は、反射前X位置(p[0])から、反射境界線(r)を引くことで、計算できるので、以下のように書くことができます。

p[0] - r

次に反射境界線(r)からの跳ね返り量を知りたいので、オレンジの部分を計算します。

反射境界線(r)から、青い部分の距離だけ左に反射させたいので、反射境界線(r)から青い部分を引きます。

r - (p[0] - r)

これが、3人目の登場人物「反射後位置」のX値になります。

補足説明

『r – (p[0] – r)』は、展開して 『r – p[0] + r』や、『r * 2 – p[0]』と書いても同じ結果になります

位置プロパティのY値に設定する値

最後に、3行目の「Y位置の値」の部分について説明します。

3行目

[(p[0] < r) ? p[0] : r - (p[0] - r), p[1]];

から、Y位置の値だけを抜き出すと

p[1]

となります。

Y位置は反射させる必要がないので、反射前Y位置(p[1])を、位置プロパティのY値にそのまま設定しています。

これが、3人目の登場人物「反射後位置」のY値になります。
これで三行目の説明はおしまいです。

[(p[0] < r) ? p[0] : r - (p[0] - r), p[1]];

上記三行目を最後にまとめると、

「基本は、XもYも反射前位置(p)を利用するけど、反射前X位置(p[0])が、反射境界線(r)の右にあった場合のみ、Xの反射位置を計算するよ」

という意味なのでした。

まとめ

ここまで書き終わって、ふと思いましたが、ここまで何人くらいの人が理解してくれたのかなーと、とても心配になっています。。

なんとなく理解できましたか?

ちなみに、変数pに代入する計算をwiggleの代わりに「time * 500」などに変更すると、単純に水平方向に反射するアニメーションになります。いろいろなアニメーションに変えてみると新たな発見があるかもしれないので、慣れてきたら色々お試しください!

感想や、わかりにくかった箇所などあれば、Xの返信や、DMなどいただけると嬉しいです。

きっと誰かの役にたっている(といいな)と信じて、次の解説記事も書いていきたいと思います!

Xのいいねやフォローもお待ちしてます!

最新情報をチェックしよう!
>Aeをもっと便利に。「COLOR CODE - AE」

Aeをもっと便利に。「COLOR CODE - AE」

AfterEffectsをもっと便利に使う為のコンテンツを制作・発信しているブログです。YouTube「COLOR CODE - AE チャンネル」では、エフェクト、エクスプレッション、プリセット、プラグインのリファレンス動画を公開しています。チャンネル登録もお待ちしています!

CTR IMG