欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

processing画一个时钟:音乐、控制转动等

程序员文章站 2022-04-27 13:26:35
...

processing画一个时钟:音乐、控制转动等

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012428012/article/details/79676759

分析

钟表的功能主要实现以下几个功能:

  1. 画钟表的表盘、数字等
  2. 通过 s 或 S 键控制旋转,t 或 T 键暂停旋转
  3. 设置音乐的定时播放、秒针转动播放音乐
  4. 右上角显示当前时间
  5. 设置时针的转动
  6. 设置分针的转动
  7. 设置秒针的转动
  8. 最终效果
1. 画钟表的表盘、数字等
  • 在屏幕中间画一个半径为150的圆
  • 表盘上一圈有60个刻度线,对应360度。因此,一个刻度线对应6度。
  • 将坐标系平移到屏幕中间,并每次旋转:每次旋转6度并画一条刻度线,总共60次。整点的刻度(如1点、3点、6点等)应该较长,所以每5次让线的更长更粗。
  • 设置3点、6点、9点、12点的文字。
    processing画一个时钟:音乐、控制转动等
void setup () {
  size(500, 500);
}
void draw () {  
  // 表盘 
  ellipseMode(CENTER);
  strokeWeight(10);
  fill(0);
  ellipse(width/2, height/2, 300, 300);

  // 刻度线
  for(int i = 1; i <= 60; i++) {
    pushMatrix();  // 拷贝一份坐标系位置
    translate(width/2, height/2);  // 移动坐标系(0,0)到(width/2, height/2)
    rotate(radians(i * 6));
    if(i % 5 == 0) { // 整点的刻度线
      strokeWeight(3);
      line(120, 0, 130, 0);
    } else { // 非整点的刻度线
      strokeWeight(1);
      line(125, 0, 130, 0);
    }
    popMatrix();  // 恢复坐标系位置
  }

  // 0-12时
  textSize(25);
  fill(255);
  stroke(255);
  strokeWeight(1);
  text(12, 235, 155); //12
  text(3, 350, 260) ;//3
  text(9, 135, 260) ;//9
  text(6, 245, 365) ;//6 
}
2. 通过 s 或 S 键控制旋转,t 或 T 键暂停旋转
  • 设置全部变量flag,用于控制时针等是否旋转
  • 按下s或S时旋转,按下t或T时停止转动
Boolean flag = true;
void draw () {  
  if (key == 's' || key == 'S') {
    flag = true;
  } else if (key=='t' || key=='T') {
    flag = false;
  } 
}
3. 设置音乐的定时播放、秒针转动播放音乐
  • 定义三个整型变量currentHour、currentMinute、currentSecond保存系统当前的时分秒信息
  • 定义两个浮点型变量currentMinuteFloat、currentHourFloat。
    • currentMinuteFloat为实际的分钟(minute() + currentSecond / 60.0)
    • currentHourFloat为实际的小时(hour() + currentMinuteFloat / 60.0)。
  • 两个if条件:设定闹钟音乐播放时间,和闹钟音乐停止时间。
  • flag为true时,秒针转动的音乐一直播放。flag为false时,秒针不转动,音乐停止播放。
import ddf.minim.*;

Minim minim;
AudioPlayer player; // 闹钟音乐
AudioPlayer player1; // 秒针转动的音乐
PImage img; // 背景图片

int currentSecond; // second,秒
int currentMinute; // minute,分
int currentHour; // hour,时
float currentMinuteFloat; // minute,分,实际分钟 minute() + currentSecond / 60.0;
float currentHourFloat; // hour,时,实际小时 hour() + currentMinuteFloat / 60.0;

void setup () {
  size(500, 500);
  img = loadImage("1.jpg");
  minim = new Minim(this); 
  player = minim.loadFile("music.mp3");
  player1 = minim.loadFile("zhongbiao1.mp3");
}

void draw () {  
    // 当前时间的时、分、秒。08:02:03,10:32:13
  currentSecond = second();
  currentMinute = minute();
  currentHour = hour();
  currentMinuteFloat = minute() + currentSecond / 60.0;
  currentHourFloat = hour() + currentMinuteFloat / 60.0;

  // 播放音乐:指定时间段内播放音乐。闹钟功能
  if (currentSecond == 30 && currentMinute == 30 && currentHour == 22) {
    player.play();
  }
  if (currentSecond == 40 && currentMinute == 30 && currentHour == 22) {
    if (player.isPlaying()) {
      player.pause();
    }
  }

  // 播放秒针转动的音乐
  if(flag) {
    if (player1.position() == player1.length()) {
      player1.rewind();
      player1.play();
    } else {
      player1.play();
    }
  } else {
    if (player1.isPlaying()) {
      player1.pause();
    }
  }
}
4. 右上角显示当前时间
  • 右上角显示当前时间:时间一般显示格式为08:02:03 或10:32:13,所以当currentSecond<10的时候,数字前面加上一个0。
  • 右上角第二行显示当前日期:调用year()/month()/day()函数显示
  • 右下角显示作品作者
    processing画一个时钟:音乐、控制转动等
void draw () {  
  // 右上角显示当前时间
  String secondBeatiful = currentSecond + "";
  String minuteBeatiful = currentMinute + "";
  String hourBeatiful = currentHour + "";
  if (currentSecond < 10) {
    secondBeatiful = "0" + currentSecond;
  }
  if (currentMinute < 10) {
    minuteBeatiful = "0" + currentMinute;
  }
  if (currentHour < 10) {
    hourBeatiful = "0" + currentHour;
  }
  String currentTime = hourBeatiful + ":" + minuteBeatiful + ":" + secondBeatiful;
  textSize(50);
  text(currentTime, width - 230, 50);
  String currentDate = year() + "/" + month() + "/" + day();
  textSize(25);
  text(currentDate, width - 150, 100);
  String author = "Author: Yuanhao Zheng";
  textSize(20);
  text(author, width - 250, height - 10);
}
5. 设置时针的转动
  • 时针转动一圈为12个小时,因此一个小时为30度。
  • 平移坐标系原点到屏幕*,然后旋转坐标系达到旋转时针的效果。
    • 当时针为3点到12点(或15点到24点)时,应该转动的角度是0到270度,所以旋转的角度为
      angleHour = radians(30 * (currentHourFloat - 3));
    • 当时针为1点到2点(或13点到14点)时,应该转动的角度是270到360度,所以旋转的角度为angleHour = radians(30 * (currentHourFloat - 1) + 300);
  • 根据之前设定好的是否转动值flag来控制坐标系转动。(flag默认是true,按下t后为false)
  • 画线:设置线条颜色(白色)和粗细(7),注意此时线条起始点和终止点的坐标都为0,横坐标不同。
void draw () {  
  // hour:时针
  // 12个小时为360度,一个小时30度。
  // 3点到12点的角度是0到270;0到3点的角度是270到360。
  pushMatrix();
  translate(width/2, height/2);
  float angleHour = radians(270);
  if ((currentHourFloat >= 3 && currentHourFloat <= 12) || (currentHourFloat >= 15 && currentHourFloat <= 24)) {
    angleHour = radians(30 * (currentHourFloat - 3));
  } else {
    angleHour = radians(30 * (currentHourFloat - 1) + 300);
  }
  if (flag) { // 判断是否按下按键,停止转动
    rotate(angleHour);
  } else {
    rotate(radians(270));
  }
  stroke(255);
  strokeWeight(7);
  line(-10, 0, 50, 0);
  popMatrix();
}
6. 设置分针的转动
  • 分针转动一圈为60分钟,因此一分钟为6度。
  • 平移坐标系原点到屏幕*,然后旋转坐标系达到旋转分针的效果。
    • 当分针为15分钟到60分钟时,应该转动的角度是0到270度,所以旋转的角度为
      angleMinute = radians(6 * (currentMinuteFloat - 15));
    • 当分针为0分钟到15分钟时,应该转动的角度是270到360度,所以旋转的角度为angleMinute = radians(270 + 6 * currentMinuteFloat);
  • 根据之前设定好的是否转动值flag来控制坐标系转动。(flag默认是true,按下t后为false)
  • 画线:设置线条颜色(白色)和粗细(5),注意此时线条起始点和终止点的坐标都为0,横坐标不同。
void draw () {  
  // minute:分针
  // 60分钟为360度,一分钟为6度。
  // 15分钟到60分钟的角度是0到270;0到15分钟的角度是270到360。
  pushMatrix();
  translate(width/2, height/2);
  float angleMinute = radians(270);
  if ((currentMinuteFloat >= 0 && currentMinute <= 15)) {
    angleMinute = radians(270 + 6 * currentMinuteFloat);
  } else {
    angleMinute = radians(6 * (currentMinuteFloat - 15));
  }
  if (flag) { // 判断是否按下按键,停止转动
    rotate(angleMinute);
  } else {
    rotate(radians(0));
  }
  stroke(255);
  strokeWeight(5);
  line(-10, 0, 70, 0);
  popMatrix();
}
7. 设置秒针的转动
  • 秒针转动一圈为60秒,因此一秒为6度。
  • 平移坐标系原点到屏幕*,然后旋转坐标系达到旋转秒针的效果。
    • 当秒针为15秒到60秒时,应该转动的角度是0到270度,所以旋转的角度为
      angleSecond = radians(6 * (currentSecond - 15));
    • 当秒针为0秒到15秒时,应该转动的角度是270到360度,所以旋转的角度为angleMinute = angleSecond = radians(270 + 6 * currentSecond);
  • 根据之前设定好的是否转动值flag来控制坐标系转动。(flag默认是true,按下t后为false)
  • 画线:设置线条颜色(红色)和粗细(3),注意此时线条起始点和终止点的坐标都为0,横坐标不同。并且还画了一个圆表示线头。
void draw () {  
  // second and ellipse:秒针
  // 60秒为360度,一秒为6度。
  // 15秒到60秒的角度是0到270;0到15秒的角度是270到360。
  pushMatrix();
  translate(width/2, height/2);
  float angleSecond = radians(270);
  if ((currentSecond >= 0 && currentSecond <= 15)) {
    angleSecond = radians(270 + 6 * currentSecond);
  } else {
    angleSecond = radians(6 * (currentSecond - 15));
  }
  if (flag) { // 判断是否按下按键,停止转动
    rotate(angleSecond);
  } else {
    rotate(radians(180));
  }
  stroke(255,0,0);
  strokeWeight(3);
  line(-15, 0, 90, 0);
  fill(255,0,0);
  ellipse(115, 0, 10, 10);
  stroke(255);
  popMatrix();
}
8. 最终效果

processing画一个时钟:音乐、控制转动等

实现代码

具体实现为:

import ddf.minim.*;

Minim minim;
AudioPlayer player;  // 闹钟音乐
AudioPlayer player1;  // 秒针转动的音乐
PImage img; // 背景图片

Boolean flag = true; // 控制是否播放音乐

// 时间相关全部变量
int currentSecond; // second,秒
int currentMinute; // minute,分
int currentHour; // hour,时
float currentMinuteFloat; // minute,分,实际分钟 minute() + currentSecond / 60.0;
float currentHourFloat; // hour,时,实际小时 hour() + currentMinuteFloat / 60.0;


void setup () {
  size(500, 500);
  img = loadImage("1.jpg");
  minim = new Minim(this); 
  player = minim.loadFile("music.mp3");
  player1 = minim.loadFile("zhongbiao1.mp3");
}

void draw () {
  // 背景图
  image(img, 0, 0, 500, 500);

  // 表盘 
  ellipseMode(CENTER);
  strokeWeight(10);
  fill(0);
  ellipse(width/2, height/2, 300, 300);

  // 刻度线
  for(int i = 1; i <= 60; i++) {
    pushMatrix();  // 拷贝一份坐标系位置
    translate(width/2, height/2);  // 移动坐标系(0,0)到(width/2, height/2)
    rotate(radians(i * 6));
    if(i % 5 == 0) { // 整点的刻度线
      strokeWeight(3);
      line(120, 0, 130, 0);
    } else { // 非整点的刻度线
      strokeWeight(1);
      line(125, 0, 130, 0);
    }
    popMatrix();  // 恢复坐标系位置
  }

  // 0-12时
  textSize(25);
  fill(255);
  stroke(255);
  strokeWeight(1);
  text(12, 235, 155); //12
  text(3, 350, 260) ;//3
  text(9, 135, 260) ;//9
  text(6, 245, 365) ;//6 

  // 判断是否按下暂停和启动键
  if (key == 's' || key == 'S') {
    flag = true;
  } else if (key == 't' || key == 'T') {
    flag = false;
  }

  // 当前时间的时、分、秒。08:02:03,10:32:13
  currentSecond = second();
  currentMinute = minute();
  currentHour = hour();
  currentMinuteFloat = minute() + currentSecond / 60.0;
  currentHourFloat = hour() + currentMinuteFloat / 60.0;

  // 播放音乐:指定时间段内播放音乐。闹钟功能
  if (currentSecond == 30 && currentMinute == 30 && currentHour == 22) {
    player.play();
  }
  if (currentSecond == 40 && currentMinute == 30 && currentHour == 22) {
    if (player.isPlaying()) {
      player.pause();
    }
  }

  // 播放秒针转动的音乐
  if(flag) {
    if (player1.position() == player1.length()) {
      player1.rewind();
      player1.play();
    } else {
      player1.play();
    }
  } else {
    if (player1.isPlaying()) {
      player1.pause();
    }
  }

  // 右上角显示当前时间
  String secondBeatiful = currentSecond + "";
  String minuteBeatiful = currentMinute + "";
  String hourBeatiful = currentHour + "";
  if (currentSecond < 10) {
    secondBeatiful = "0" + currentSecond;
  }
  if (currentMinute < 10) {
    minuteBeatiful = "0" + currentMinute;
  }
  if (currentHour < 10) {
    hourBeatiful = "0" + currentHour;
  }
  String currentTime = hourBeatiful + ":" + minuteBeatiful + ":" + secondBeatiful;
  textSize(50);
  text(currentTime, width - 230, 50);
  String currentDate = year() + "/" + month() + "/" + day();
  textSize(25);
  text(currentDate, width - 150, 100);
  String author = "Author: Yuanhao Zheng";
  textSize(20);
  text(author, width - 250, height - 10);



  // hour:时针
  // 12个小时为360度,一个小时30度。
  // 3点到12点的角度是0到270;0到3点的角度是270到360。
  pushMatrix();
  translate(width/2, height/2);
  float angleHour = radians(270);
  if ((currentHourFloat >= 3 && currentHourFloat <= 12) || (currentHourFloat >= 15 && currentHourFloat <= 24)) {
    angleHour = radians(30 * (currentHourFloat - 3));
  } else {
    angleHour = radians(30 * (currentHourFloat - 1) + 300);
  }
  if (flag) { // 判断是否按下按键,停止转动
    rotate(angleHour);
  } else {
    rotate(radians(270));
  }
  stroke(255);
  strokeWeight(7);
  line(-10, 0, 50, 0);
  popMatrix();



  // minute:分针
  // 60分钟为360度,一分钟为6度。
  // 15分钟到60分钟的角度是0到270;0到15分钟的角度是270到360。
  pushMatrix();
  translate(width/2, height/2);
  float angleMinute = radians(270);
  if ((currentMinuteFloat >= 0 && currentMinute <= 15)) {
    angleMinute = radians(270 + 6 * currentMinuteFloat);
  } else {
    angleMinute = radians(6 * (currentMinuteFloat - 15));
  }
  if (flag) { // 判断是否按下按键,停止转动
    rotate(angleMinute);
  } else {
    rotate(radians(0));
  }
  stroke(255);
  strokeWeight(5);
  line(-10, 0, 70, 0);
  popMatrix();



  // second and ellipse:秒针
  // 60秒为360度,一秒为6度。
  // 15秒到60秒的角度是0到270;0到15秒的角度是270到360。
  pushMatrix();
  translate(width/2, height/2);
  float angleSecond = radians(270);
  if ((currentSecond >= 0 && currentSecond <= 15)) {
    angleSecond = radians(270 + 6 * currentSecond);
  } else {
    angleSecond = radians(6 * (currentSecond - 15));
  }
  if (flag) { // 判断是否按下按键,停止转动
    rotate(angleSecond);
  } else {
    rotate(radians(180));
  }
  stroke(255,0,0);
  strokeWeight(3);
  line(-15, 0, 90, 0);
  fill(255,0,0);
  ellipse(115, 0, 10, 10);
  stroke(255);
  popMatrix();

}


void keyPressed() {
  if (key == 'z' || key == 'Z') {
    player.pause();
  }
  if (key == 'x' || key == 'X') {
    player.play();
  }
  if (key == 'c' || key == 'C') {
    player.rewind();
  }
}

实现代码2(函数版)

抽象成函数,具体实现为:

import ddf.minim.*;

Minim minim;
AudioPlayer player;  // 闹钟音乐
AudioPlayer player1;  // 秒针转动的音乐
PImage img; // 背景图片

Boolean flag = true; // 控制是否播放音乐

// 时间相关全部变量
int currentSecond; // second,秒
int currentMinute; // minute,分
int currentHour; // hour,时
float currentMinuteFloat; // minute,分,实际分钟 minute() + currentSecond / 60.0;
float currentHourFloat; // hour,时,实际小时 hour() + currentMinuteFloat / 60.0;

void setup () {
  size(500, 500);
  img = loadImage("1.jpg");
  minim = new Minim(this); 
  player = minim.loadFile("music.mp3");
  player1 = minim.loadFile("zhongbiao1.mp3");
}

void draw () {
  // 背景图
  image(img, 0, 0, 500, 500);
  // 计算当前时间的时、分、秒。08:02:03,10:32:13
  currentSecond = second();
  currentMinute = minute();
  currentHour = hour();
  currentMinuteFloat = minute() + currentSecond / 60.0;
  currentHourFloat = hour() + currentMinuteFloat / 60.0;  
  // 画钟表的基本形状  
  drawClock();
  // 播放音乐
  playMusic(); 
  // 右上角显示当前时间和日期
  showTimeAndDate();  
  // hour:时针
  hourPointer();
  // minute:分针
  minutePointer();  
  // second and ellipse:秒针
  secondPointer();
}



// 画钟表的基本形状 
void drawClock() {
  // 表盘 
  ellipseMode(CENTER);
  strokeWeight(10);
  fill(0);
  ellipse(width/2, height/2, 300, 300); 

  // 刻度线
  for(int i = 1; i <= 60; i++) {
    pushMatrix();  // 拷贝一份坐标系位置
    translate(width/2, height/2);  // 移动坐标系(0,0)到(width/2, height/2)
    rotate(radians(i * 6));
    if(i % 5 == 0) { // 整点的刻度线
      strokeWeight(3);
      line(120, 0, 130, 0);
    } else { // 非整点的刻度线
      strokeWeight(1);
      line(125, 0, 130, 0);
    }
    popMatrix();  // 恢复坐标系位置
  }

  // 0-12时
  textSize(25);
  fill(255);
  stroke(255);
  strokeWeight(1);
  text(12, 235, 155); //12
  text(3, 350, 260) ;//3
  text(9, 135, 260) ;//9
  text(6, 245, 365) ;//6 
}



// 判断是否按下暂停和启动键
void keyPressed() {
  // 判断是否按下暂停和启动键
  if (key == 's' || key == 'S') {
    flag = true;
  } else if (key=='t' || key=='T') {
    flag = false;
  }
}



// 播放音乐
void playMusic() {
  // 播放音乐:指定时间段内播放音乐。闹钟功能
  if (currentSecond == 30 && currentMinute == 30 && currentHour == 22) {
    player.play();
  }
  if (currentSecond == 40 && currentMinute == 30 && currentHour == 22) {
    if (player.isPlaying()) {
      player.pause();
    }
  }

  // 播放秒针转动的音乐
  if(flag) {
    if (player1.position() == player1.length()) {
      player1.rewind();
      player1.play();
    } else {
      player1.play();
    }
  } else {
    if (player1.isPlaying()) {
      player1.pause();
    }
  }
}



// 右上角显示当前时间和日期
void showTimeAndDate() {
  // 右上角显示当前时间。08:02:03,10:32:13
  String secondBeatiful = currentSecond + "";
  String minuteBeatiful = currentMinute + "";
  String hourBeatiful = currentHour + "";
  if (currentSecond < 10) {
    secondBeatiful = "0" + currentSecond;
  }
  if (currentMinute < 10) {
    minuteBeatiful = "0" + currentMinute;
  }
  if (currentHour < 10) {
    hourBeatiful = "0" + currentHour;
  }
  String currentTime = hourBeatiful + ":" + minuteBeatiful + ":" + secondBeatiful;
  textSize(50);
  text(currentTime, width - 230, 50);
  String currentDate = year() + "/" + month() + "/" + day();
  textSize(25);
  text(currentDate, width - 150, 100);
  String author = "Author: Yuanhao Zheng";
  textSize(20);
  text(author, width - 250, height - 10);
}



// hour:时针
void hourPointer() {
  // hour:时针
  // 12个小时为360度,一个小时30度。
  // 3点到12点的角度是0到270;0到3点的角度是270到360。
  pushMatrix();
  translate(width/2, height/2);
  float angleHour = radians(270);
  if ((currentHourFloat >= 3 && currentHourFloat <= 12) || (currentHourFloat >= 15 && currentHourFloat <= 24)) {
    angleHour = radians(30 * (currentHourFloat - 3));
  } else {
    angleHour = radians(30 * (currentHourFloat - 1) + 300);
  }
  if (flag) { // 判断是否按下按键,停止转动
    rotate(angleHour);
  } else {
    rotate(radians(270));
  }
  stroke(255);
  strokeWeight(7);
  line(-10, 0, 50, 0);
  popMatrix();
}



// minute:分针
void minutePointer() {
  // minute:分针
  // 60分钟为360度,一分钟为6度。
  // 15分钟到60分钟的角度是0到270;0到15分钟的角度是270到360。
  pushMatrix();
  translate(width/2, height/2);
  float angleMinute = radians(270);
  if ((currentMinuteFloat >= 0 && currentMinute <= 15)) {
    angleMinute = radians(270 + 6 * currentMinuteFloat);
  } else {
    angleMinute = radians(6 * (currentMinuteFloat - 15));
  }
  if (flag) { // 判断是否按下按键,停止转动
    rotate(angleMinute);
  } else {
    rotate(radians(0));
  }
  stroke(255);
  strokeWeight(5);
  line(-10, 0, 70, 0);
  popMatrix();
}



// second and ellipse:秒针
void secondPointer() {
  // second and ellipse:秒针
  // 60秒为360度,一秒为6度。
  // 15秒到60秒的角度是0到270;0到15秒的角度是270到360。
  pushMatrix();
  translate(width/2, height/2);
  float angleSecond = radians(270);
  if ((currentSecond >= 0 && currentSecond <= 15)) {
    angleSecond = radians(270 + 6 * currentSecond);
  } else {
    angleSecond = radians(6 * (currentSecond - 15));
  }
  if (flag) { // 判断是否按下按键,停止转动
    rotate(angleSecond);
  } else {
    rotate(radians(180));
  }
  stroke(255,0,0);
  strokeWeight(3);
  line(-15, 0, 90, 0);
  fill(255,0,0);
  ellipse(115, 0, 10, 10);
  stroke(255);
  popMatrix();
}

实现代码3(函数 + 数组)

将时间相关的变量放到数组中,具体实现为:

import ddf.minim.*;

Minim minim;
AudioPlayer player;  // 闹钟音乐
AudioPlayer player1;  // 秒针转动的音乐
PImage img; // 背景图片

Boolean flag = true; // 控制是否播放音乐

// 时间相关全部变量
int[] time = new int[3]; // 数组:秒、分、时
float[] timeFloat = new float[2];
//int currentSecond; // second,秒
//int currentMinute; // minute,分
//int currentHour; // hour,时
//float currentMinuteFloat; // minute,分,实际分钟 minute() + currentSecond / 60.0;
//float currentHourFloat; // hour,时,实际小时 hour() + currentMinuteFloat / 60.0;

void setup () {
  size(500, 500);
  img = loadImage("1.jpg");
  minim = new Minim(this); 
  player = minim.loadFile("music.mp3");
  player1 = minim.loadFile("zhongbiao1.mp3");
}

void draw () {
  // 背景图
  image(img, 0, 0, 500, 500);

  // 计算当前时间的时、分、秒。08:02:03,10:32:13
  time[0] = second();
  time[1] = minute();
  time[2] = hour();
  timeFloat[0] = minute() + time[0] / 60.0;
  timeFloat[1] = hour() + timeFloat[0] / 60.0;
  //currentSecond = second();
  //currentMinute = minute();
  //currentHour = hour();
  //currentMinuteFloat = minute() + currentSecond / 60.0;
  //currentHourFloat = hour() + currentMinuteFloat / 60.0;  


  // 画钟表的基本形状  
  drawClock();
  // 播放音乐
  playMusic(); 
  // 右上角显示当前时间和日期
  showTimeAndDate();  
  // hour:时针
  hourPointer();
  // minute:分针
  minutePointer();  
  // second and ellipse:秒针
  secondPointer();
}



// 画钟表的基本形状 
void drawClock() {
  // 表盘 
  ellipseMode(CENTER);
  strokeWeight(10);
  fill(0);
  ellipse(width/2, height/2, 300, 300); 

  // 刻度线
  for(int i = 1; i <= 60; i++) {
    pushMatrix();  // 拷贝一份坐标系位置
    translate(width/2, height/2);  // 移动坐标系(0,0)到(width/2, height/2)
    rotate(radians(i * 6));
    if(i % 5 == 0) { // 整点的刻度线
      strokeWeight(3);
      line(120, 0, 130, 0);
    } else { // 非整点的刻度线
      strokeWeight(1);
      line(125, 0, 130, 0);
    }
    popMatrix();  // 恢复坐标系位置
  }

  // 0-12时
  textSize(25);
  fill(255);
  stroke(255);
  strokeWeight(1);
  text(12, 235, 155); //12
  text(3, 350, 260) ;//3
  text(9, 135, 260) ;//9
  text(6, 245, 365) ;//6 
}



// 判断是否按下暂停和启动键
void keyPressed() {
  // 判断是否按下暂停和启动键
  if (key == 's' || key == 'S') {
    flag = true;
  } else if (key=='t' || key=='T') {
    flag = false;
  }
}



// 播放音乐
void playMusic() {
  // 播放音乐:指定时间段内播放音乐。闹钟功能
  if (time[0] == 30 && time[1] == 30 && time[2] == 22) {
    player.play();
  }
  if (time[0] == 40 && time[1] == 30 && time[2] == 22) {
    if (player.isPlaying()) {
      player.pause();
    }
  }

  // 播放秒针转动的音乐
  if(flag) {
    if (player1.position() == player1.length()) {
      player1.rewind();
      player1.play();
    } else {
      player1.play();
    }
  } else {
    if (player1.isPlaying()) {
      player1.pause();
    }
  }
}



// 右上角显示当前时间和日期
void showTimeAndDate() {
  // 右上角显示当前时间。08:02:03,10:32:13
  String secondBeatiful = time[0] + "";
  String minuteBeatiful = time[1] + "";
  String hourBeatiful = time[2] + "";
  if (time[0] < 10) {
    secondBeatiful = "0" + time[0];
  }
  if (time[1] < 10) {
    minuteBeatiful = "0" + time[1];
  }
  if (time[2] < 10) {
    hourBeatiful = "0" + time[2];
  }
  String currentTime = hourBeatiful + ":" + minuteBeatiful + ":" + secondBeatiful;
  textSize(50);
  text(currentTime, width - 230, 50);
  String currentDate = year() + "/" + month() + "/" + day();
  textSize(25);
  text(currentDate, width - 150, 100);
  String author = "Author: Yuanhao Zheng";
  textSize(20);
  text(author, width - 250, height - 10);
}



// hour:时针
void hourPointer() {
  // hour:时针
  // 12个小时为360度,一个小时30度。
  // 3点到12点的角度是0到270;0到3点的角度是270到360。
  pushMatrix();
  translate(width/2, height/2);
  float angleHour = radians(270);
  if ((timeFloat[1] >= 3 && timeFloat[1] <= 12) || (timeFloat[1] >= 15 && timeFloat[1] <= 24)) {
    angleHour = radians(30 * (timeFloat[1] - 3));
  } else {
    angleHour = radians(30 * (timeFloat[1] - 1) + 300);
  }
  if (flag) { // 判断是否按下按键,停止转动
    rotate(angleHour);
  } else {
    rotate(radians(270));
  }
  stroke(255);
  strokeWeight(7);
  line(-10, 0, 50, 0);
  popMatrix();
}



// minute:分针
void minutePointer() {
  // minute:分针
  // 60分钟为360度,一分钟为6度。
  // 15分钟到60分钟的角度是0到270;0到15分钟的角度是270到360。
  pushMatrix();
  translate(width/2, height/2);
  float angleMinute = radians(270);
  if ((timeFloat[0] >= 0 && timeFloat[0] <= 15)) {
    angleMinute = radians(270 + 6 * timeFloat[0]);
  } else {
    angleMinute = radians(6 * (timeFloat[0] - 15));
  }
  if (flag) { // 判断是否按下按键,停止转动
    rotate(angleMinute);
  } else {
    rotate(radians(0));
  }
  stroke(255);
  strokeWeight(5);
  line(-10, 0, 70, 0);
  popMatrix();
}



// second and ellipse:秒针
void secondPointer() {
  // second and ellipse:秒针
  // 60秒为360度,一秒为6度。
  // 15秒到60秒的角度是0到270;0到15秒的角度是270到360。
  pushMatrix();
  translate(width/2, height/2);
  float angleSecond = radians(270);
  if ((time[0] >= 0 && time[0] <= 15)) {
    angleSecond = radians(270 + 6 * time[0]);
  } else {
    angleSecond = radians(6 * (time[0] - 15));
  }
  if (flag) { // 判断是否按下按键,停止转动
    rotate(angleSecond);
  } else {
    rotate(radians(180));
  }
  stroke(255,0,0);
  strokeWeight(3);
  line(-15, 0, 90, 0);
  fill(255,0,0);
  ellipse(115, 0, 10, 10);
  stroke(255);
  popMatrix();
}

实现代码4(函数 + 类)

将时间相关的抽象成一个类,具体实现为:

import ddf.minim.*;

Minim minim;
AudioPlayer player;  // 闹钟音乐
AudioPlayer player1;  // 秒针转动的音乐
PImage img; // 背景图片

Boolean flag = true; // 控制是否播放音乐


// 时间类
class Time {
  // 时间相关全部变量
  int currentSecond; // second,秒
  int currentMinute; // minute,分
  int currentHour; // hour,时
  float currentMinuteFloat; // minute,分,实际分钟 minute() + currentSecond / 60.0;
  float currentHourFloat; // hour,时,实际小时 hour() + currentMinuteFloat / 60.0;

  // 构造函数,函数名和类名(Time)相同,没有返回类型
  Time(int s, int m, int h, float mf, float hf) {
    currentSecond = s;
    currentMinute = m;
    currentHour = h;
    currentMinuteFloat = mf;
    currentHourFloat = hf;
  }

}


void setup () {
  size(500, 500);
  img = loadImage("1.jpg");
  minim = new Minim(this); 
  player = minim.loadFile("music.mp3");
  player1 = minim.loadFile("zhongbiao1.mp3");
}

void draw () {
  // 背景图
  image(img, 0, 0, 500, 500);
  // 计算当前时间的时、分、秒。08:02:03,10:32:13
  int s = second();
  int m = minute();
  int y = hour();
  float mf = minute() + s / 60.0;
  float hf = hour() + mf / 60.0;
  Time time = new Time(s, m, y, mf, hf);
  // 画钟表的基本形状  
  drawClock();
  // 播放音乐
  playMusic(time); 
  // 右上角显示当前时间和日期
  showTimeAndDate(time);  
  // hour:时针
  hourPointer(time);
  // minute:分针
  minutePointer(time);  
  // second and ellipse:秒针
  secondPointer(time);
}



// 画钟表的基本形状 
void drawClock() {
  // 表盘 
  ellipseMode(CENTER);
  strokeWeight(10);
  fill(0);
  ellipse(width/2, height/2, 300, 300); 

  // 刻度线
  for (int i = 1; i <= 60; i++) {
    pushMatrix();  // 拷贝一份坐标系位置
    translate(width/2, height/2);  // 移动坐标系(0,0)到(width/2, height/2)
    rotate(radians(i * 6));
    if (i % 5 == 0) { // 整点的刻度线
      strokeWeight(3);
      line(120, 0, 130, 0);
    } else { // 非整点的刻度线
      strokeWeight(1);
      line(125, 0, 130, 0);
    }
    popMatrix();  // 恢复坐标系位置
  }

  // 0-12时
  textSize(25);
  fill(255);
  stroke(255);
  strokeWeight(1);
  text(12, 235, 155); //12
  text(3, 350, 260) ;//3
  text(9, 135, 260) ;//9
  text(6, 245, 365) ;//6
}



// 判断是否按下暂停和启动键
void keyPressed() {
  // 判断是否按下暂停和启动键
  if (key == 's' || key == 'S') {
    flag = true;
  } else if (key=='t' || key=='T') {
    flag = false;
  }
}



// 播放音乐
void playMusic(Time time) {
  // 播放音乐:指定时间段内播放音乐。闹钟功能
  if (time.currentSecond == 30 && time.currentMinute == 30 && time.currentHour == 22) {
    player.play();
  }
  if (time.currentSecond == 40 && time.currentMinute == 30 && time.currentHour == 22) {
    if (player.isPlaying()) {
      player.pause();
    }
  }

  // 播放秒针转动的音乐
  if (flag) {
    if (player1.position() == player1.length()) {
      player1.rewind();
      player1.play();
    } else {
      player1.play();
    }
  } else {
    if (player1.isPlaying()) {
      player1.pause();
    }
  }
}



// 右上角显示当前时间和日期
void showTimeAndDate(Time time) {
  // 右上角显示当前时间。08:02:03,10:32:13
  String secondBeatiful = time.currentSecond + "";
  String minuteBeatiful = time.currentMinute + "";
  String hourBeatiful = time.currentHour + "";
  if (time.currentSecond < 10) {
    secondBeatiful = "0" + time.currentSecond;
  }
  if (time.currentMinute < 10) {
    minuteBeatiful = "0" + time.currentMinute;
  }
  if (time.currentHour < 10) {
    hourBeatiful = "0" + time.currentHour;
  }
  String currentTime = hourBeatiful + ":" + minuteBeatiful + ":" + secondBeatiful;
  textSize(50);
  text(currentTime, width - 230, 50);
  String currentDate = year() + "/" + month() + "/" + day();
  textSize(25);
  text(currentDate, width - 150, 100);
  String author = "Author: Yuanhao Zheng";
  textSize(20);
  text(author, width - 250, height - 10);
}



// hour:时针
void hourPointer(Time time) {
  // hour:时针
  // 12个小时为360度,一个小时30度。
  // 3点到12点的角度是0到270;0到3点的角度是270到360。
  pushMatrix();
  translate(width/2, height/2);
  float angleHour = radians(270);
  if ((time.currentHourFloat >= 3 && time.currentHourFloat <= 12) || (time.currentHourFloat >= 15 && time.currentHourFloat <= 24)) {
    angleHour = radians(30 * (time.currentHourFloat - 3));
  } else {
    angleHour = radians(30 * (time.currentHourFloat - 1) + 300);
  }
  if (flag) { // 判断是否按下按键,停止转动
    rotate(angleHour);
  } else {
    rotate(radians(270));
  }
  stroke(255);
  strokeWeight(7);
  line(-10, 0, 50, 0);
  popMatrix();
}



// minute:分针
void minutePointer(Time time) {
  // minute:分针
  // 60分钟为360度,一分钟为6度。
  // 15分钟到60分钟的角度是0到270;0到15分钟的角度是270到360。
  pushMatrix();
  translate(width/2, height/2);
  float angleMinute = radians(270);
  if ((time.currentMinuteFloat >= 0 && time.currentMinute <= 15)) {
    angleMinute = radians(270 + 6 * time.currentMinuteFloat);
  } else {
    angleMinute = radians(6 * (time.currentMinuteFloat - 15));
  }
  if (flag) { // 判断是否按下按键,停止转动
    rotate(angleMinute);
  } else {
    rotate(radians(0));
  }
  stroke(255);
  strokeWeight(5);
  line(-10, 0, 70, 0);
  popMatrix();
}



// second and ellipse:秒针
void secondPointer(Time time) {
  // second and ellipse:秒针
  // 60秒为360度,一秒为6度。
  // 15秒到60秒的角度是0到270;0到15秒的角度是270到360。
  pushMatrix();
  translate(width/2, height/2);
  float angleSecond = radians(270);
  if ((time.currentSecond >= 0 && time.currentSecond <= 15)) {
    angleSecond = radians(270 + 6 * time.currentSecond);
  } else {
    angleSecond = radians(6 * (time.currentSecond - 15));
  }
  if (flag) { // 判断是否按下按键,停止转动
    rotate(angleSecond);
  } else {
    rotate(radians(180));
  }
  stroke(255, 0, 0);
  strokeWeight(3);
  line(-15, 0, 90, 0);
  fill(255, 0, 0);
  ellipse(115, 0, 10, 10);
  stroke(255);
  popMatrix();
}
相关标签: processing