====== 時計の再構成 ======
ここまで様々な情報の再構成を練習してきました。デザインの対象となるものはどのような要素で構成されており、その素材はどのような特性を持つのか。これはアナログでもデジタルでもそれほど違いはありません。利用する要素の特性を正しく捉えることで、再構成をすることが可能になります。再構成は自由に意見できるように思うかもしれませんが、技術的、素材的、機能的制約があるため、それらを把握していないとどこまで実現できるかのイメージがつかなくなってしまいます。このページでは再構成練習の仕上げとして、時計を題材として外観、機能を同時にモジュール化して、再度構成し直す手順をプログラミングで体験してみます。時計の機能は時間(時、分、秒等)をユーザに提示することですので、基本的にはこれが提示できれば時計としては成立します。一方で時計とひとえに言ってもみなさん様々なデザインやプロダクトを思い浮かべることができると思います。機能はシンプルですが、その提示方法(UI)を変更することで時計のデザインは無限大に存在すると言えます。
例えば以下はセイコーが2017年にグッドデザイン・ロングライフデザイン賞を受賞した製品(https://www.seiko-clock.co.jp/news/2017/20171004.html)です。
{{ :lecture:design_with_prototyping:seiko.jpeg?400 |}}
この他スイス国鉄の駅舎時計でよくしられる[[https://www.mondainewatch.jp/history/|MONDAINE社のステーションクロック]]やデンマーク国内鉄道で広く採用された[[https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwjv7_nphbrqAhXNaN4KHW4UA-IQmhMwDXoECAoQAg&url=https%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%25E3%2582%25A2%25E3%2583%25AB%25E3%2583%258D%25E3%2583%25BB%25E3%2583%25A4%25E3%2582%25B3%25E3%2583%2596%25E3%2582%25BB%25E3%2583%25B3&usg=AOvVaw1lpMR1WRrZVchM6dIUuOYD|アルネ・ヤコブセン]]による[[https://arnejacobsen-time.jp/wallclock_station.html|STATIONクロック]]、同じくデンマークのプロダクトデザイナーの[https://ja.wikipedia.org/wiki/ヤコブ・イェンセン|ヤコブ・イェンセン]]、この他[[https://ja.wikipedia.org/wiki/ジョージ・ネルソン|ジョージ・ネルソン]]やメーカーではjunghansの時計もよく知られています。あなたの好きなデザイナーを見つけたらその人の時計デザインを見てみるのも面白いですね。
この他、時計文化はPCのスクリーンセイバーにおいても定着していますので、そちらの観点からもユニークなものがたくさん見つけられます。
* https://www.screensaversplanet.com/screensavers/themes/clocks
* https://screensaverclocks.com
* [[https://www.google.co.jp/search?q=clock+screensaver&source=lnms&tbm=isch&sa=X&ved=2ahUKEwjKvf-ll7rqAhWGwJQKHa-pBaUQ_AUoAXoECAsQAw&biw=1508&bih=1312|google画像検索]]
===== アナログ時計 =====
では早速時計を作っていきます。今回は下記の画像に示すような時計を制作してみます。だいぶステーションクロックに引っ張られてますが、代表的なシンプル時計をつくります。
{{ :lecture:設計指示書.png?link&400 |}}
==== 時間の取得 ====
まずはhour, minute, secondの情報を取得します。Processingにはすでに[[https://processing.org/examples/clock.html|Exampleとしてclock]]が含まれているので、こちらを参照してみても良いかもしれません。hour, minute, secondはそのままの関数名で利用できます。
* hour() : 今の時を返す
* minute(): 今の分を返す
* second(): 今の秒を返す
というわけで、まずはこの値をそのまま画面上に表示してみます。
void setup()
{
size(500, 500);
textAlign(CENTER,CENTER);
textSize(48);
}
void draw()
{
background(0);
text(str(hour())+":"+str(minute())+":"+str(second()), width/2, height/2);
}
textAlignの設定だけでは微妙に文字が縦方向に中央になっていませんが、ちゃんと中央に合わせたい人は[[https://qiita.com/akspect/items/14962dbe0b7d45627b4e|このページ]]をご参照ください。
==== 針を描く ====
では次は針を描いてみます。すでに時間は取得済みなのでこの変数を利用して針の角度を計算します。それぞれの値の範囲は
* hour: 0-24(ただし24=0)
* minute: 0-60(ただし60=0)
* second: 0-60(ただし60=0)
なので、これらの変数を
* hour: 0-24 -> 0-360
* minute: 0-60 -> 0-360
* second: 0-60 -> 0-360
になるように値を変換する必要がります。Processingにはmapという関数がすでにありますので、こちらを利用して値の変換を行います。もちろん自分で変換式を書いてもらっても構いません。この他、画面の中心座標を予めcx,cyとして値を代入しておきます。
float cx,cy;
void setup()
{
size(500, 500);
textAlign(CENTER,CENTER);
textSize(48);
cx = width/2;
cy = height/2;
}
void draw()
{
background(255);
fill(100);
text(str(hour())+":"+str(minute())+":"+str(second()), width/2, height/2+200);
// 長針、短針、秒針の表示
// それぞれの時刻に合わせて、針を回転させるべき角度を計算しています。
float s = radians(map(second(), 0, 60, 0, 360)-90); // 秒針
float m = radians(map(minute(), 0, 60, 0, 360)-90); // 分針
float h = radians(map(hour()%12, 0, 12, 0, 360)-90); // 時針
// 秒針、分針、時針の描画
{
stroke(50, 50, 50);
strokeWeight(15);
line(cx, cy, cx + cos(h) * 100, cy + sin(h) * 100);
strokeWeight(10);
line(cx, cy, cx + cos(m) * 100, cy + sin(m) * 100);
stroke(255, 0, 0);
strokeWeight(2);
line(cx, cy, cx + cos(s) * 100, cy + sin(s) * 100);
}
}
==== 針の動きに連続性(スイープ型)をもたせる ====
ここまでのプログラムを実行してみて気づいた方もいるかもしれませんが、実は時針、分針の動きが秒針が60のところで「カク」っと動く動作になっているのがわかると思います。この動きのことをステップ型とよんでいます。一方で、例えば11時59分であれば、時針の指す番号は11ではなく、12にだいぶ寄った位置を指していて欲しいですね。そこでそのような振る舞い(スイープ型)になるようにプログラムを修正します。具体的には norm()という関数を利用します。この関数は与えられた範囲を0.0 - 1.0の範囲に修正してくれます。
float cx,cy;
void setup()
{
size(500, 500);
textAlign(CENTER,CENTER);
textSize(48);
cx = width/2;
cy = height/2;
}
void draw()
{
background(255);
fill(100);
text(str(hour())+":"+str(minute())+":"+str(second()), width/2, height/2+200);
// 長針、短針、秒針の表示
// それぞれの時刻に合わせて、針を回転させるべき角度を計算しています。
float s = radians(map(second(), 0, 60, 0, 360)-90); // 秒針
float m = radians(map(minute()+norm(second(),0,60), 0, 60, 0, 360)-90); // 分針
float h = radians(map(hour()%12+norm(minute(),0,60), 0, 12, 0, 360)-90); // 時針
// 秒針、分針、時針の描画
{
stroke(50, 50, 50);
strokeWeight(15);
line(cx, cy, cx + cos(h) * 100, cy + sin(h) * 100);
strokeWeight(10);
line(cx, cy, cx + cos(m) * 100, cy + sin(m) * 100);
stroke(255, 0, 0);
strokeWeight(2);
line(cx, cy, cx + cos(s) * 100, cy + sin(s) * 100);
}
}
これで時針及び分針はなだらかに動くようになりました。一方で秒針はステップ型のままです。この秒針もスイープ型にする場合は、Processingでsecond()以下の細かな時間間隔を取得する必要があるため、プログラムを自分で実装する必要があります。興味があればチャレンジしてみましょう。
===== 刻みを入れる =====
では最後に刻み(tics)を入れていきます。
float cx,cy;
void setup()
{
size(500, 500);
textAlign(CENTER,CENTER);
textSize(48);
cx = width/2;
cy = height/2;
}
void draw()
{
background(255);
fill(100);
text(str(hour())+":"+str(minute())+":"+str(second()), width/2, height/2+200);
// 刻み(nick)の表示
fill(50, 50, 50);
for ( int a = -90; a < 360-90; a = a + 6 ) {
float angle = radians(a);
float length;
stroke(10);
if ( a%30 == 0) {
length = 100/6.0;
strokeWeight(10);
} else {
length = 100/10.0;
strokeWeight(1);
}
stroke(0, 0, 0, 50);
line(
cx+cos(angle)*(100-length), cy+sin(angle)*(100-length),
cx+cos(angle)*(100), cy+sin(angle)*(100)
);
}
// 長針、短針、秒針の表示
// それぞれの時刻に合わせて、針を回転させるべき角度を計算しています。
float s = radians(map(second(), 0, 60, 0, 360)-90); // 秒針
float m = radians(map(minute()+norm(second(),0,60), 0, 60, 0, 360)-90); // 分針
float h = radians(map(hour()%12+norm(minute(),0,60), 0, 12, 0, 360)-90); // 時針
// 秒針、分針、時針の描画
{
stroke(50, 50, 50);
strokeWeight(15);
line(cx, cy, cx + cos(h) * 100, cy + sin(h) * 100);
strokeWeight(10);
line(cx, cy, cx + cos(m) * 100, cy + sin(m) * 100);
stroke(255, 0, 0);
strokeWeight(2);
line(cx, cy, cx + cos(s) * 100, cy + sin(s) * 100);
}
}
===== 微調整 =====
では最後に微調整をします。針の長さ等をすべて変数に置き換えて、最初のスケッチに近づけます。完成したものが以下のプログラムになります。ダウンロードして確認してみましょう。
* 完成品:{{ :lecture:プロトタイピング基礎:clock_template.zip |}}