お絵かきプログラミングProcessingサンプルコード解説の第9弾です!
ProcessingをまだPCに導入されていない方は、こちらの記事を参考に導入してみてください!
今回は Clock というサンプルコードを見てみましょう。
難易度は ★★☆☆☆ くらい。処理自体は基本的ですが、応用範囲の広い関数がたくさん登場します。
わからない箇所があればコメントをください。
Table of Contents
もくじ
とりあえず動かしてみよう
Processnigを起動し、サンプルコードを開きましょう。
ファイル → サンプル と選択し現れたウィンドウで Basics → Input → Clock と選択してください。
このようなスケッチが現れます。ウィンドウの左上にある再生ボタンをクリックして実行してみましょう。
時計が出ます。
今回のコードは 現在時刻を取得や三角関数を用いた図形の描画を扱います。基礎的で使用場面の多い技なのでぜひ身につけていってください!
コードを読む
とりあえずコードの全貌を確認しましょう。
そこそこの長さですね。では上からみていきましょう。
まずコメントから始まっていますね。
「現在時刻は second()、minute()、hour()で取得できる。このプログラムでは時計の針の位置を設定するのにsin()、cos() を使っているよ」と言っています。
これから読むべきコードの説明までしてくれて、とても丁寧ですね。
まずはグローバル変数を確認しましょう。
現時点では使われ方はわかりませんが以下のようだと想像できます。(もちろんこの時点での想像に過ぎないので間違っている可能性はあります。)
変数 | 意味 |
---|---|
cx | 何かのx座標? |
cy | 何かのy座標? |
secondsRadius | 秒針の半径? |
minutesRadius | 分針の半径? |
hoursRadius | 時針の半径? |
clockDiameter | 時計の直径 |
radias(半径)、diameter(直径)が使い分けられている点はややこしいので注意しましょう。
ちなみに cx, cyはまとめて一行で宣言されていますが、二行に分けて書いても同じ動作になります。
ではsetup()の中身を見てみましょう。
setup
size()は毎度おなじみのウィンドウサイズを指定する関数です。
stroke()もよくみる関数ですね。線の色を設定します。今回は白に設定しています。
ここから後は各変数への代入を行っています。
radiusを宣言し、これに適当に倍率をかけて設定していますね。
radiusはウィンドウの縦横の短い方の値の半分になっています。今は意味はよくわからないので、とりあえずsetup()を通じて宣言済みの各変数に値が入ったことだけ覚えておきましょう。
次にdraw()を見てみます。
draw
一見長く見えますが、全体象を遠くからみてもらうと、似たようなコードが繰り返し書かれていることがわかると思います。あまり構えず順にみていきましょう。
まずは毎度おなじみbackground()ですね。ウィンドウ全体を一色で塗りつぶす関数です。今回のサンプルコードは、draw()が呼ばれるたびに直前の画面を消すことがわかります。
fill()は塗りの色を設定する関数ですね。引数が一つの場合はグレースケースでの指定となり、真っ黒が0、真っ白が255として灰色の濃さを指定できます。今回は80なので、黒寄りの灰色ですね。
noStroke()は枠線を描かないようにする関数です。多分このあと円を描くために準備していると想像できます。
ellipse()も毎度お馴染みの関数です。楕円を描きます。今回の引数は、半径はx方向・y方向とも同じ値を指定しているので、中心(cx, cy) 直径 clockDiameter の円を描きます。
setup()で設定した変数が使われていますね。cx、cyは予想通り円の中心として使われていましたね。
次に行きましょう。
まずコメントがありますね。
「sin()、cos()の角度は3時から始まるよ。上端から始めるためにHALF_PIを引くよ。」
Processingに慣れていない状態で読むと、結構意味不明だと思います。笑
ここで座標の取り方が重要になります。Processingの座標軸は数学で習ってきた座標とは異なることを覚えておいてください。 この座標軸なら回転角の始点は3時方向であり、角度が増加すると時計回りの方向に進むことがわかると思います。そのため、角度を -π/2 すれば始点が12時方向になり、時計と同じ動きになります。
ところでHALF_PIはπ/2を表す定数です。Processingでは他にもπ/4を表すQUARTE_PIや、2πを表すTAUなどの定数が用意されています。
ここからs、m、hが宣言されていますが、これは変数名から秒、分、時に対応する何かと想像できます。
map()はこれまであまり出てきていなかった関数ですが、とても便利なのでここで覚えましょう!
second()によって秒の値は0~59のいずれかの整数が入りますが、sin()のドキュメントを読むと、引数は弧度法で0~6.28(2π)です。したがって変換が必要なのですが、その変換を行うのに便利なのが、map() です。一言で言うと、写像してくれます。
ある値と変換前・変換後の区間を与えると、変換後の区間での相当する値を返してくれます。
例えばsecond()の値が30だった場合、mapされた後の値はπとなります。
(ちなみに、map()を使う代わりに変換のための式を自分で用意し使用することでも同様の処理を実現可能です。)
ここまでの処理でほぼ確定しますが、sは秒針が時計の中心と角度と予想されます。つまりm、hはそれぞれ分針、時針の角度です。
ただmとhの処理も同様かというと…実は少し違います。
map()の一つ目の引数をみて欲しいのですが、秒の時はsecond()を入れていましたが、分の時はminute()に何か足していますね?
norm()は値の正規化を行います。実はmap()の特殊な場合です。
map()は変換後の値の範囲を指定しましたが、norm()はその範囲が0~1に限定されています(なのでmap()で代用することもできます)。
今回は分針の角度を分数だけでなく秒数によっても変化させるためにこの調整をいれているんですね。
ところで時針の角度を求める際、map()の5つめの引数(変換後の区間の最大値)は TWO_PIではなく、TWO_PI * 2 となっています。時計の時針の動きを考えるとわかると思います。考えてみましょう。
もうすぐ終わりです。頑張りましょう!
コメントには「時計の針を描画する」と書いてあります。
stroke()はもう出ましたね。線の色を指定します。
strokeWeight()は線の太さを指定します。
line()は線を描画します。引数は二つの端点のx、y座標です。
一つ目のline()は秒針を描画しています。座標の向きに注意しましょう。
分針、時針の描画は同様なので省略します。
次が最後です!
コメントには「minute ticksを描画する」と書いてありますね。(minute ticksとは時計の文字盤一周分に打たれた60個の点のことのようです。日本語にはこれを表す言葉はないかもしれません…。)
strokeWeight()はもう説明しましたね。省略します。
beginShape()は初めて出てきましたね。これは複雑な図形を描画するための関数です。あとで説明します。
次にaのループが始まっていますが、文字盤の点は6度ごとに1つ打つため、6刻みで360までになっています。
radians()は角度の単位を「度」から「実数(弧度法)」に変換する関数です。sin()もcos()も引数は実数をとるのでこの変換が必要になります。例えば radians(30)=π/6、radians(180)=π、などとなります。
x、yはよく見るとさっきの秒針の端点と同じ値ですね。なのでvertex(x, y)によって点が打たれますが、その位置は秒針の端点に一致します。
この点の描画が文字盤一周に対して行われています。
ループを抜けるとendShape()がありますが、これはbeginShape()に対応する関数で、図形描画の終了直後に配置します。
さっき説明を飛ばしたbeginnShape()の引数ですが、POINTSを指定していますが、これによりさっきvertex()で指定した座標の点をそのまま点として描画します。引数の選択次第では全ての点を結ぶなどの様々な描画ができます。興味がある方は調べてみてください。
これで完成です!お疲れ様でした!!
さいごに
今回は、時間の取得と三角関数などを用いた図形の描画を学びました。
処理自体はわかりやすかったと思いますが、関数の選択により読みやすさが変わりやすい部分でもあります。いろんな関数を知って、うまく選択することを意識しましょう!
ではまた次回!