人工言語入門 A 2010
Processingで時計を作る
今日の内容
- 最終課題のテーマ発表
- 最終課題に関連した演習
- 基礎:普通のアナログ時計を作る
- 時刻の取得
 - 時刻の情報から針の角度を計算する
 - より正確な時計にしていくには?
 
 - 応用:単純な図形で「時間」を表現する
- 位置による時間の表現
 - 数による時間の表現
 - 色による時間の表現
 - 形態による時間の表現 …etc
 
 
 - 基礎:普通のアナログ時計を作る
 
 - 最終課題に関連した演習
 
最終課題について
テーマ:Processingを用いて「時間」を表現する
- Processingを用いて、「時間」を表現するプログラムを作成してください。
- 時間を表現するといっても、普段身近に接している時計を作成するという意味ではなく、いままで見たことのないような表現手段で「時間」を感じさせる方法を考えてください。
 
 - 作品の完成度よりは、斬新なアイデアを重視します。
 - 完成したプログラムは下記のWebサーバのアドレスにアップロードすることで提出したこととします。
 - http://www.cuc.ac.jp/~[ログイン名]/proga/final/index.html
 
時計を作る 1 – アナログ時計を作る
- 課題の内容と関連して、まずは普通のアナログ時計を作成する
- 時刻の取得
 - 取得した時刻から、秒針、分針、時針の角度を計算する
 
 - 時刻を取得するための関数
 - 取得される時刻は、コンピュータのOSに設定された時刻
 
//秒の取得
second();
//分の取得
minute();
//時の取得
hour();
- 試しに現在の秒数を取得して、出力してみる
 - println() を利用して、Processingのコンソールのテキストエリアに現在の秒数を表示してみる
 
void setup() {
  frameRate(30);
}
void draw() {
  int h = hour();
  int m = minute();
  int s = second();
  println("現在の時刻は "+h+":"+m+":"+s);
}
- 取得した「時」「分」「秒」の値から針の角度を計算する
 - それぞれの1単位あたり、何度針が動くのか計算する (角速度)
- 時間
- 12時間で時計を1周する
 - 1時間あたりの移動角度 → 360/12 = 30°
 
 - 分
- 60分で時計を1周する
 - 1分あたりの移動角度 → 360/60 = 6°
 
 - 秒
- 60秒で時計を1周する
 - 1秒あたりの移動角度 → 360/60 = 6°
 
 
 - 時間
 - 現在の時刻の値にそれぞれの角速度をかけ算すると、現在の角度が算出されるはず
 - 時刻から、針の角度を計算する
- 例:8時30分20秒
- 時針:8 x 30 = 240°
 - 分針:30 x 6 = 180°
 - 秒新:20 x 6 = 120°
 
 
 - 例:8時30分20秒
 

- Processingのプロラムで表現してみる
- 座標系全体を画面の中央に移動 translate(width/2, height/2);
 - 時刻を取得
 - 時間の針
- pushMatrix();
 - rotate(時間 x 15°);
 - popMatrix();
 
 - 分の針
- pushMatrix();
 - rotate(時間 x 6°);
 - popMatrix();
 
 - 秒の針
- pushMatrix();
 - rotate(時間 x 6°);
 - popMatrix();
 
 
 - Processingの rotate() 関数で用いられる角度の単位に注意する必要あり
 - 角度の単位は「度 (degree)」ではなく「ラジアン (radian)」で指定しなくてはならない
- Processingでの、degreeからradianへの変換
- radians( 度 );
 
 - radianからdegreeへの変換
- degrees( ラジアン角 );
 
 
 - Processingでの、degreeからradianへの変換
 

void setup() {
  size(300,300);
  stroke(255);
  smooth();
  frameRate(30);
}
void draw() {
  background(0);
  float s = second();
  float m = minute();
  float h = hour() % 12;
  translate(width/2, height/2);
  ellipse(0,0,width,height);
  noFill();
  stroke(255);
  //秒針
  pushMatrix();
  rotate(radians(s*(360/60)));
  strokeWeight(1);
  line(0,0,0,-height/2);
  popMatrix();
  //分針
  pushMatrix();
  rotate(radians(m*(360/60)));
  strokeWeight(2);
  line(0,0,0,-height/2);
  popMatrix();
  //時針
  pushMatrix();
  rotate(radians(h*(360/12)));
  strokeWeight(4);
  line(0,0,0,-height/3);
  popMatrix();
}

実際の時計との違い
- 作成したプログラムの表示と実際のアナログ時計と比べてみる
- なにか違いはないだろうか?
- 分が切り替わった瞬間の動き
 - 時間が切り替わった瞬間の動き
 
 
 - なにか違いはないだろうか?
 - 実際の時計
- 時針、分針も常にゆっくりと動いている
 - 時刻が変化した瞬間に動くのではなく、ゆっくりと移動して、気がつくと角度が変化している
 
 
- 実際の分針
- 秒の影響を受けている
 - 毎秒あたり、1/60の影響 (1分 = 60秒なので)
 - m = m + (s/60);
 
 - 実際の時針
- 分の影響を受けている
 - 毎分あたり、1/60の影響 (1時間 = 60分なので)
 - h = h + (m/60);
 
 - 実際にアナログ時計の動きと同じになるよう、プログラムを改良する
 
void setup() {
  size(300,300);
  stroke(255);
  smooth();
  frameRate(30);
}
void draw() {
  background(0);
  float s = second();
  float m = minute() + (s/60.0);
  float h = hour()%12 + (m/60.0);
  translate(width/2, height/2);
  ellipse(0,0,width,height);
  noFill();
  stroke(255);
  //秒針
  pushMatrix();
  rotate(radians(s*(360/60)));
  strokeWeight(1);
  line(0,0,0,-height/2);
  popMatrix();
  //分針
  pushMatrix();
  rotate(radians(m*(360/60)));
  strokeWeight(2);
  line(0,0,0,-height/2);
  popMatrix();
  //時針
  pushMatrix();
  rotate(radians(h*(360/12)));
  strokeWeight(4);
  line(0,0,0,-height/3);
  popMatrix();
}

- 文字盤を追加
- 角度を変更しながら、一定間隔に目盛を刻んでいく
 - 小さな目盛:6度づつ
 - 大きな目盛:30度づつ
 
 
int MARGIN = 20;
void setup() {
  size(300,300);
  stroke(255);
  smooth();
  frameRate(30);
}
void draw() {
  background(0);
  float s = second();
  float m = minute() + (s/60.0);
  float h = hour()%12 + (m/60.0);
  translate(width/2, height/2);
  rotate(radians(180));
  // 文字盤の表示
  pushMatrix();
  fill(128);
  noStroke();
  for(int i=0; i<60; i++){
    rotate(radians(6));
    ellipse(width/2-MARGIN,0,3,3);
  }
  for(int i=0; i<12; i++){
    rotate(radians(30));
    ellipse(width/2-MARGIN,0,10,10);
  }
  popMatrix();
  noFill();
  stroke(255);
  // 秒針
  pushMatrix();
  rotate(radians(s*(360/60)));
  strokeWeight(1);
  line(0,0,0,width/2-MARGIN);
  popMatrix();
  // 分針
  pushMatrix();
  rotate(radians(m*(360/60)));
  strokeWeight(2);
  line(0,0,0,width/2-MARGIN);
  popMatrix();
  // 時針
  pushMatrix();
  rotate(radians(h*(360/12)));
  strokeWeight(4);
  line(0,0,0,width/3-MARGIN);
  popMatrix();
}

アナログ時計 OOP版
int MARGIN = 20;
Clock myClock = new Clock();
void setup() {
  size(300,300);
  stroke(255);
  smooth();
  frameRate(30);
}
void draw() {
  background(0);
  myClock.getTime();
  myClock.draw();
}
class Clock {
  float s, m, h;
  Clock(){
  }
  void getTime(){
    s = second();
    m = minute() + (s/60.0);
    h = hour()%12 + (m/60.0);
  }
  void draw(){
    translate(width/2, height/2);
    rotate(radians(180));
    pushMatrix();
    fill(128);
    noStroke();
    for(int i=0; i<60; i++){
      rotate(radians(6));
      ellipse(width/2-MARGIN,0,3,3);
    }
    for(int i=0; i<12; i++){
      rotate(radians(30));
      ellipse(width/2-MARGIN,0,10,10);
    }
    popMatrix();
    noFill();
    stroke(255);
    pushMatrix();
    rotate(radians(s*(360/60)));
    strokeWeight(1);
    line(0,0,0,width/2-MARGIN);
    popMatrix();
    pushMatrix();
    rotate(radians(m*(360/60)));
    strokeWeight(2);
    line(0,0,0,width/2-MARGIN);
    popMatrix();
    pushMatrix();
    rotate(radians(h*(360/12)));
    strokeWeight(4);
    line(0,0,0,width/3-MARGIN);
    popMatrix();
  }
}

