yoppa.org


人工言語入門 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°
  • 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( ラジアン角 );
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();
  }
}