前回こちらの記事でProcessingというお絵かきプログラミングの導入を説明しました。
導入がまだの人は上記事を参考に導入してみてください。
Processingは初心者に優しいことに、サンプルコードが用意されています。
サンプルコードは実行するだけでそこそこ面白いものが描けます。が、このコードでなぜその絵がかけるのかを理解するのは、ある程度の努力がいります。
というわけでサンプルコードを解説していきます。
説明は全てMac版での画面を示しながら行いますが、Windows版でもほとんど同じものが現れると思います。
わからない箇所があればコメントをください。
今回扱うのは「Array2D」という名前のサンプルコードです。
難易度は ★★★☆☆ くらい。
Table of Contents
もくじ
サンプルコードを開こう
まずProcessingを起動してください。そして、メニューバーから「ファイル」→「サンプル」とたどってください。
現れたウィンドウで 「Basics」→「Arrays」→「Array2D」 を選択してください。
こんなスケッチが現れるはずです。これでサンプルの呼び出しは完了で、コードが手元に表示されます。
とりあえず実行してみましょう。実行するにはスケッチ左上にある再生ボタン(三角形のマークの描かれているもの)をクリックします。
点がたくさん並んだこんな画像が現れます。ここから後は、この絵が描かれていく仕組みを説明していきます。
とりあえず上から読んでみる
少しずつ進めていきましょう。各コードには左端に行数を示しています。サンプルコード内での対応を確認しながら読み進めてください。
プログラムはコメントで始まっていますね。内容を読んでみると、
「二次元配列の作りかただよ。二次元配列の値は二つのインデックスを使って取り出すんだ。二次元配列は画像の保管に使えるよ。この例では、各ピクセルは中心からの距離によって色をつけられてるんだ。」
と言っています。このサンプルはタイトルの通り、二次元配列の使い方デモのようです。
ここで変数を宣言していますね。コメントに「距離によって色をつけてある」と書いてあったので、distancesやmaxDistanceという変数が定義されているのは納得です。ただspacerはまだよくわかりません。
ところで
これは14行目と27行目の抜粋ですが、setupという関数が定義されています。これについては一旦飛ばして後で説明します。
ではsetupの中をみていきましょう。
初めにsizeという関数が現れますが、これは描画する画像のサイズを設定する関数です。引数の2つの数は横の長さ、縦の長さの順になっており、今回の画像は横長の長方形になります。ちなみに単位はピクセルです。
先ほど宣言した変数maxDistance、distancesに値を代入していますね。
maxDistanceはdistで指定されています。
distは点と点の間の距離を取得する関数です。
今回は(width/2, height/2)と(width, height)の間の距離となっています。
widthとheightは宣言されることなく現れましたが、これらはそれぞれ画像の横の長さ、縦の長さを表しています。
したがってmaxDistanceは中心と右下角の距離です。意味を考えても、納得の命名ですね。
width, heightのような便利な変数は今後もたくさん現れます。
次はfor文です。
distanceという変数が宣言されていますね。distancesと似ていますが、違います。
distanceは2点(weight/2, height/2), (x, y)の間の距離です。distancesは2次元の配列でしたが、これは(x, y)の組ごとのdistanceの値を保持しているんですね。
spacerは、まだ謎です。
strokeWeightは図形を描画する時の線の太さを指定します。
noLoopは一旦置いておきます。
Processingの実行順
ここで急ですが、さっき出てきたsetupの説明をするためProcessingでのコードの挙動を説明します。
ここまで説明してきた部分はsetupという名前の関数ブロックに含まれていました。一方、これから後の部分はdrawという名前の関数ブロックに含まれます。
結論からいうと、setupより前の部分が一度だけ実行され、setupは一度だけ実行され、drawは無限ループされます。無限ループは動画を描画する際に必要になってくるのですが、今回は不要です。
setup中に書かれているnoLoopはこのdraw内のループを停止させる関数です。noLoopが書かれた時点でsetupとdrawには機能としての違いは無くなるので、今回は実は敢えてコードを分けて書く必要はありません。
ではdraw内に進みましょう。
backgroundは画像の背景色を指定します。今回は0となっていますが、これは「黒」を表します。
次のコメント部分は
「この埋め込まれたループはspacerの値だけ飛ばしながら配列の値を取得する。したがって配列には、描かれてる以上の値が存在する。spacerの値を変えて点の密度を変えてみよう。」
と言っています。ついにspacerの説明が出てきましたね。
直後のループを見てみると、distances配列は画像内の全てのピクセルに対して定義されていたのですが、spacerの値は10なので、10ピクセルごとにdistancesの値が取得され、strokeの引数となっています。
strokeは描画される点や線などの色を設定します。引数にdistancesを取っているので、距離に応じて色を変化させているようです。
pointは点を描きます。画像中のたくさんの点はこの関数で描かれていたのですね。
ちょっとアレンジしてみよう
仕組みを理解できたら、コードを色々アレンジしてみましょう。
サンプルコードは内容を変更しても上書き保存はできないので、変更後のコードを残しておきたい方は、別ファイルとして保存してください。
今回はspacer, strokeWeightを変えてみましょう。
まずはstrokeWeightだけを変更します。
描かれる絵はどのように変わるでしょう?
隣り合う点がちょうど接するようになりましたね。strokeWeightの数字とspacerの数字が一致しているからです。
次はもうちょっと思い切った変更をしてみましょう。
どうなるでしょう。
点が大きくなりすぎて重なっていますね。
ちなみに、点の境界に目を凝らして重なりの順番を確認すると、左よりも右のほうが、上よりも下のほうが後に描かれていることがわかります。図の矢印の順に描かれています。
この描画の順番は、コード中の点を描く部分でのfor文の書き方により決定されています。
yのループの中にxのループがあります。x、yはそれぞれ横軸、縦軸の座標を表していますから、
「右へ一列分の点を描ききってから、下に一列分だけずれる。」という操作を繰り返すことになります。
作品によっては絵の各要素が描画される順番が重要になることもあります。ループがどのように機能するのか、意識していきましょう。
おわりに
今回はProcessingで使われる関数の中でもかなり基本的なもののみを使いました。
コードを理解していると、自分の好きなようにアレンジすることが可能なので、自分の作品に取り入れられるようになります。
ソフトウェアの公式サンプルは、その品質が保証されているわけですから、学習に向いていると思います。
是非とも他人のコードからたくさん学んでください。