一个用Processing做的趣味画板

这是一个用processing写的趣味画板,是我和室友一起做的一个小玩意儿。

画板的功能介绍如下图所示。在这里插入图片描述
菜单栏详细介绍:
保存/另存为 :可以打开本地的文件夹选择器,默认存储格式为jpg,若用户指定格式,则以用户指定的格式存储图片。保存按钮在使用过一次后,再次点击不会打开文件夹选择器,而是保存到之前填写的存储位置。
背景颜色 :该画板的颜色模式为HSB模式,背景颜色选择区域是一个120x100的矩形区域,点击背景颜色时会清空绘画区域。
画笔颜色 :同背景颜色,只不过点击画笔颜色不会清空绘画区域。
图形选择 :该画板比较简单,图形较少,只有线条,随机圆,移动圆,矩形,圆角矩形,中心对称,花朵(图片),花朵(图形)。

画板的主界面如图所示:
在这里插入图片描述
在这里插入图片描述
下面就是这个画板的代码了,由四个标签组成,其中三个为class。
DrawPanel_mainfile:

String pic_name="line";          //用于记录图形
PFont font;                //字体
int strokeSize=1;        //用于记录描边粗细
color strokeColor;    //用于记录描边颜色
color backColor;  //用于记录绘画区域的背景颜色
int key_d_=0;      //用于记录帮助是否打开
String filename;    //用于记录之前保存的文件名
//以下四个变量用于画矩形
float x1,x2,y1,y2;      //用于记录按钮按下和松开时的坐标
int j1=0;      //用于记录是否有鼠标按下的坐标
int j2=0;      //用于记录是否有鼠标松开的坐标
int d_;        //用于矩形记录鼠标是否按下
//移动圆所需变量
int move_circle_d=0;        //用于移动圆记录鼠标是否按下
//圆角矩形所需变量
float rcx1,rcx2,rcy1,rcy2;      
int rcj1=0;      
int rcj2=0;      
int rcd_;  
//中心对称所需变量
float csx,csy;
int csj=0;
int csd_;
int line_count=6;      //该整数用于记录当前中心对称所产生的线条数
//花朵所需变量
float flowerSize=50;  //定义一个全局变量用于增加花朵大小
//可填充颜色的花朵所需变量
PShape s;    //创建一个图形对象用来存储花朵的形状
float jiaodu;    //用来画花朵弧形的函数
float size=0;    //用来记录花朵的大小
color colora=color(random(0,120),random(0,120),random(0,100));    //记录花朵的随机颜色
//按钮图标
PImage[] img=new PImage[13];
MoveCircle[] mcs=new MoveCircle[0];
void setup(){
  background(255);
  colorMode(HSB, 100);    //设置颜色模式为HSB模式
  backColor=color(0,0,120);      
  fill(backColor);
  rect(-1,121,1001,680);
  size(1000,800);
  font=createFont("KaiTi-48.vlw",30);    //创建字体为楷体
  textFont(font);        //将楷体设置为默认字体
  textSize(30);
  frameRate(30);
  for(int i=0;i<13;i++){
    img[i]=loadImage(i+".png");
  }
  //创建图形(花朵)
  s=createShape();
  s.beginShape();
  s.fill(0);
  s.noStroke();
  for(int i=-40;i<=40;i++){
   s.vertex(i,-i*i/10*0.6); 
  }
  for(int i=40;i>=-40;i--){
   jiaodu=map(i,40,-40,30,150);
   s.vertex(i,-112-40*(sin(radians(jiaodu))-0.5));
  }
  s.endShape();
  //分割线......
  fill(0);
  line(0,120,1000,120);
  line(210,0,210,120);
  line(210,60,500,60);
  line(500,0,500,120);
  line(750,0,750,120);
  line(610,0,610,120);
  line(860,0,860,120);
  image(img[1],110,15,90,90);   //另存为
  image(img[2],220,5,50,50);    //线条
  image(img[3],275,5,50,50);    //随机圆
  image(img[4],330,5,50,50);    //移动圆
  image(img[5],385,5,50,50);    //矩形
  image(img[6],440,5,50,50);    //圆角矩形
  image(img[7],220,65,50,50);   //中心对称
  image(img[8],275,65,50,50);   //花朵
  image(img[9],330,65,50,50);    //可填充颜色的花朵
  image(img[10],510,10,90,90);   //背景颜色
  image(img[11],760,10,90,90);  //画笔颜色 
  //提示帮助的文字
  noFill();
  rect(385,60,105,60);
  text("帮助(H)",385,100);
  //初始的描边颜色
  strokeColor=color(0,0,0);
  //通过画point来产生一块区域表示颜色选择区域
  for (int i = 0; i < 120; i++) {
    for (int j = 0; j < 100; j++) {
      stroke(i, j, 120);
      point(620+i, 10+j);
    }
  }
  for (int i = 0; i < 120; i++) {
    for (int j = 0; j < 100; j++) {
      stroke(i, j, 120);
      point(870+i, 10+j);
    }
  }
}
void draw(){
  //之所以把保存按钮放在draw()函数里是为了消除一个移动圆带来的bug,通过重新产生一个矩形和保存按钮,
  //来清除移动圆在(0,0)位置产生的痕迹
  fill(0,0,120);
  noStroke();
  rect(0,0,52,52);
  image(img[0],10,15,90,90);    //保存
  ShapeType st=new ShapeType(pic_name);    //创建图形对象
  st.drawShape();     //调用画图函数
  mouseStyle();
}
void mouseReleased()  {
//当点击按钮时,改变pic_name,并修改按钮颜色
  if(mouseX>220&&mouseX<270&&mouseY>5&&mouseY<55){
    pic_name="line";              //线条
  }else if(mouseX>275&&mouseX<325&&mouseY>5&&mouseY<55){
    pic_name="random_circle";      //随机圆
  }else if(mouseX>330&&mouseX<380&&mouseY>5&&mouseY<55){
   pic_name="move_circle";        //移动圆
  }else if(mouseX>385&&mouseX<435&&mouseY>5&&mouseY<55){
   pic_name="rect";              //矩形
  }else if(mouseX>440&&mouseX<490&&mouseY>5&&mouseY<55){
   pic_name="radius_rect";      //圆角矩形
  }else if(mouseX>220&&mouseX<270&&mouseY>65&&mouseY<115){
   pic_name="center_shape";     //中心对称
  }else if(mouseX>275&&mouseX<325&&mouseY>65&&mouseY<115){
   pic_name="flower";           //花朵图片
  }else if(mouseX>330&&mouseX<380&&mouseY>65&&mouseY<115){
   pic_name="color_flower";       //可填充颜色的花朵
  }
  else if(mouseX>870&&mouseX<990&&mouseY>10&&mouseY<110){
    strokeColor=color(mouseX-870,mouseY-10,120);      //画笔颜色
  }else if(mouseX>620&&mouseX<740&&mouseY>10&&mouseY<110&&key_d_==0){      //背景颜色
   backColor=color(mouseX-620,mouseY-10,120); 
   fill(backColor);
   noStroke();
   rect(-1,121,1001,680); 
   mcs=new MoveCircle[0];    //需要清空储存移动圆的数组
  }else if(mouseX>385&&mouseX<490&&mouseY>60&&mouseY<120){
   openHelp();              //调用打开帮助函数 
  }else if(mouseX>120&&mouseX<210&&mouseY>15&&mouseY<105){
    selectOutput("请选择一个文件夹:","selectFile");        //另存为
  }else if(mouseX>10&&mouseX<100&&mouseY>15&&mouseY<105){
    if(filename==null){
      selectOutput("请选择一个文件夹:","selectFile_");      //保存
    }else{
      save(filename); 
    }
  }
}
//另存为调用的函数
void selectFile(File selection){
  if(selection==null){
  }else{    
    if(selection.getAbsolutePath().indexOf(".")>0){  //若用户再文件名处写了后缀
      save(selection.getAbsolutePath());       //以用户规定的格式保存
    }else{
      save(selection.getAbsolutePath()+".jpg");  //默认保存为jpg格式
    }
  }
}
//保存调用的函数,之所以保存与另存为要分开写,是为了filename的正确存储,另存为按钮并不会filename传值
//这样点击另存为之后,再点保存按钮,不会保存到另存为设置的文件路径。这样filename就只能存储保存按钮
//输入的文件存储路径了
void selectFile_(File selection){
  if(selection==null){
  }else{    
    if(selection.getAbsolutePath().indexOf(".")>0){   //若用户再文件名处写了后缀
      save(selection.getAbsolutePath());       //以用户规定的格式保存
      filename=selection.getAbsolutePath();      //将文件名保存下来
    }else{
      save(selection.getAbsolutePath()+".jpg");    //默认保存为jpg格式
      filename=selection.getAbsolutePath()+".jpg";      //将文件名保存下来
    }
  }
}
//键盘监听函数
void keyReleased(){
  char k=key;
  switch(k){
    case 'c':
      fill(backColor);
      noStroke();
      rect(-1,121,1001,680); 
      mcs=new MoveCircle[0];
      break;
    case 'C':
      fill(backColor);
      noStroke();
      rect(-1,121,1001,680); 
      mcs=new MoveCircle[0];
      break;
    case 'h':
      openHelp();    //调用打开帮助的函数
      break;
    case 'H':
      openHelp();
      break;
    case '0':
      strokeSize=0;
      break;
    case '1':
      strokeSize=1;
      break;
    case '2':
      strokeSize=2;
      break;
    case '3':
      strokeSize=3;
      break;
    case '4':
      strokeSize=4;
      break;
    case '5':
      strokeSize=5;
      break;
    case '6':
      strokeSize=6;
      break;
    case '7':
      strokeSize=7;
      break;
    case '8':
      strokeSize=8;
      break;
    case '9':
      strokeSize=9;
      break;
    case 'w':
      line_count+=1;
      break;
    case 's':
      line_count-=1;
      break;
  }
}
//打开、关闭帮助的函数
void openHelp(){
  if(key_d_==0){
        //先用矩形覆盖背景颜色的区域,然后将帮助图片加载上去
        noStroke();
        fill(0,0,120);
        rect(510,0,230,120);
        image(img[12],510,10,230,100);
        key_d_=1; 
      }else{
        //同理用矩形覆盖帮助图片区域,再讲背景颜色的区域重新绘制一边
        noStroke();
        fill(0,0,120);
        rect(510,10,230,110);
        stroke(0,0,0);
        strokeWeight(1);
        line(610,0,610,120);
        for (int i = 0; i < 120; i++) {
          for (int j = 0; j < 100; j++) {
            stroke(i, j, 120);
            point(620+i, 10+j);
          }
        }
        image(img[10],510,10,90,90);    
        key_d_=0; 
      }
}
//监听鼠标样式的函数
void mouseStyle(){
  if(mouseX>220&&mouseX<270&&mouseY>5&&mouseY<55){
    cursor(HAND);
  }else if(mouseX>275&&mouseX<325&&mouseY>5&&mouseY<55){
    cursor(HAND);
  }else if(mouseX>330&&mouseX<380&&mouseY>5&&mouseY<55){
   cursor(HAND);
  }else if(mouseX>385&&mouseX<435&&mouseY>5&&mouseY<55){
   cursor(HAND);
  }else if(mouseX>440&&mouseX<490&&mouseY>5&&mouseY<55){
   cursor(HAND);
  }else if(mouseX>220&&mouseX<270&&mouseY>65&&mouseY<115){
   cursor(HAND);
  }else if(mouseX>275&&mouseX<325&&mouseY>65&&mouseY<115){
   cursor(HAND);
  }else if(mouseX>330&&mouseX<380&&mouseY>65&&mouseY<115){
   cursor(HAND);
  }else if(mouseX>870&&mouseX<990&&mouseY>10&&mouseY<110){
    cursor(CROSS);
  }else if(mouseX>620&&mouseX<740&&mouseY>10&&mouseY<110&&key_d_==0){      
   cursor(CROSS);
  }else if(mouseX>385&&mouseX<490&&mouseY>60&&mouseY<120){
   cursor(HAND); 
  }else if(mouseX>120&&mouseX<210&&mouseY>15&&mouseY<105){
    cursor(HAND);
  }else if(mouseX>10&&mouseX<100&&mouseY>15&&mouseY<105){
    cursor(HAND);
  }else{
   cursor(ARROW); 
  }
}

ShapeType_class:

class ShapeType{
  String shape_name;
  
  //有参构造函数,获取代表形状的参数shape_name
  ShapeType(String pic_name){
    shape_name=pic_name;
  }
  
  //绘画函数,根据shapename来判断需要画什么图形
  public void drawShape(){
    //当图形为线条时
    if(shape_name=="line"){
      frameRate(300);
      strokeWeight(strokeSize);
      stroke(strokeColor);
      if(mousePressed&&mouseY>140){
        line(mouseX,mouseY,pmouseX,pmouseY);
      }
    }
    
    //当图形为随机圆时
    if(shape_name=="random_circle"){
      frameRate(8);                  //修改帧速率,防止图形产生过快覆盖了原图形
      noStroke();
      if(mousePressed&&(mouseButton==LEFT)&&mouseY>140){
        int r=(int)random(25,45);    //随机产生圆半径
        int R=(int)random(0,255);    //随机red值
        int G=(int)random(0,255);    //随机green值
        int B=(int)random(0,255);    //随机blue值
        int A=(int)random(0,255);    //随机透明度
        fill(R,G,B,A);
        ellipse(mouseX,mouseY,r,r);
      }
    }
    
    //当图形为移动圆形时
    if(shape_name=="move_circle"){
      frameRate(50);
      noStroke();    //去掉描边
      if(mouseY>140){
        if(mousePressed){
          move_circle_d=1;
        }else{
          if(move_circle_d==1){
             MoveCircle mc=new MoveCircle(mouseX,mouseY,strokeColor,strokeSize);
             mcs=(MoveCircle[])append(mcs,mc);    //用append函数添加新元素到对象数组中
          }
          move_circle_d=0;
        }
      }
      for(int i=0;i<mcs.length;i++){
         mcs[i].move();       //遍历对象数组,依次移动数组中的圆
      }
    }
    
    //当图形为矩形时
    if(shape_name=="rect"){   
      frameRate(30);
      noStroke();
      if(mouseY>140){
      if(mousePressed){
          d_=1;
          j2=0;
          if (j1==0) //按下鼠标时记录此时的鼠标坐标
          {
            j1=1;
            x1=mouseX;
            y1=mouseY;
          }    
        }else{
          if (d_==1) {
            fill(strokeColor);
            j1=0;
            if (j2==0) //松开鼠标时记录此时的鼠标坐标
            {
              j2=1;
              x2=mouseX;
              y2=mouseY;
            }
            quad(x1, y1, x1, y2, x2, y2, x2, y1);    //只需在松开鼠标时绘画,用四边形,不能用矩形
            d_=0;
          }
        } 
      } 
    }
    
    //当图形为圆角矩形时
    if(shape_name=="radius_rect"){
      frameRate(100);
      strokeWeight(strokeSize);
      stroke(strokeColor);
      if(mouseY>140){
      if(mousePressed){
          rcd_=1;
          rcj2=0;
          if (rcj1==0) //按下鼠标时记录此时的鼠标坐标
          {
            rcj1=1;
            rcx1=mouseX;
            rcy1=mouseY;
          }
        }else{
          if (rcd_==1) {
            fill(255);
            rcj1=0;
            if (rcj2==0) //松开鼠标时记录此时的鼠标坐标
            {
              rcj2=1;
              rcx2=mouseX;
              rcy2=mouseY;
            }
            //quad(rcx1, rcy1, rcx1, rcy2, rcx2, rcy2, rcx2, rcy1);
            float rcr=min(abs(rcx1-rcx2),abs(rcy1-rcy2))/3.0;    //圆角半径
            float rct;    //用于交换坐标值时作为中间量
            //交换角点值,使得rcx1,rcy1为左上角的坐标,rcx2,rcy2为右下角坐标
            if(rcx1>rcx2){
             rct=rcx1;rcx1=rcx2;rcx2=rct;
            }
            if(rcy1>rcy2){
             rct=rcy1;rcy1=rcy2;rcy2=rct; 
            }
            fill(strokeColor);
            arc(rcx1+rcr/2,rcy1+rcr/2,rcr,rcr,PI,PI+HALF_PI);
            arc(rcx2-rcr/2,rcy1+rcr/2,rcr,rcr,PI+HALF_PI,TWO_PI);
            arc(rcx2-rcr/2,rcy2-rcr/2,rcr,rcr,0,HALF_PI);
            arc(rcx1+rcr/2,rcy2-rcr/2,rcr,rcr,HALF_PI,PI);
            rect(rcx1,rcy1+rcr/2,rcx2-rcx1,rcy2-rcr-rcy1);
            rect(rcx1+rcr/2,rcy1,rcx2-rcr-rcx1,rcy2-rcy1);
            rcd_=0;
          }
        } 
      } 
    }
    
    //当图形为中心对称图形时
    if(shape_name=="center_shape"){
      frameRate(300);
      strokeWeight(strokeSize);
      stroke(strokeColor);
      if(mouseY>140){
        if(mousePressed){
          csd_=1;
          if(csj==0){
            csj=1;
            csx=mouseX;
            csy=mouseY;
          }
          translate(csx,csy);           //移动坐标系
          if(dist(mouseX-csx,mouseY-csy,0,0)<(csy-140)){    //约束中心对称的大小,避免画到工具栏上面
            for(int i=0;i<line_count;i++){  
                line(mouseX-csx,mouseY-csy,pmouseX-csx,pmouseY-csy);          
                rotate(TWO_PI/line_count);                      //旋转坐标系
              }
            }
        }else{
          if(csd_==1){
            csj=0;
          }
          csd_=0;
        }
      }
    }
    
    //当图形为花朵时
    if(shape_name=="flower"){
      frameRate(15);
      if(mouseY>150){
        if(mousePressed){
            Flower f=new Flower(mouseX, mouseY);
            f.show();
        }else{
          flowerSize=50;
        }
      }
    }
    
    //当图形为可填充颜色的花朵时
    if(shape_name=="color_flower"){
      frameRate(10);
      if(mouseY>150){
        if(mousePressed){  
          translate(mouseX,mouseY);
          scale(flowerSize/100-0.3+size);
          s.beginShape();
          s.fill(strokeColor);
          s.endShape();
          if(size<=0.6&&mouseY-(132*(0.2+size))>120){
            for(int j=0;j<6;j++){       
              shape(s,0,0); 
              rotate(radians(72));
            }
            fill(colora);
            ellipse(0,0,40,40);
            size+=0.03;
          }
        }else{
          colora=color(random(0,120),random(0,120),random(0,100));
          size=0;
        }
      }
    }  
  }
}

MoveCircle_class:

class MoveCircle{
 float x,y,x1,y1;
 float xspeed,yspeed;
 color circleColor;
 int size;
 MoveCircle(float a,float b,color c,int d){
   x=a;
   y=b;
   circleColor=c;    //圆形颜色
   size=d+1;      //记录当前strokeSize,+1是为了保证size!=0,因为圆形半径=size*10
   xspeed=random(-1,1);
   yspeed=random(-1,1);
 }
 void move(){
   //每隔一段时间修改一次圆形速度,为了修改周期与帧速率匹配,需要设定一个范围
   if(millis()%1000<10||millis()%1000>990&&millis()%1000<1000){
       xspeed=random(-1,1);
       yspeed=random(-1,1);
     }
   x+=xspeed;
   y+=yspeed;
   fill(backColor);
   ellipse(x1,y1,10*size+2,size*10+2);  //该圆形用于清除前一个圆,做到"伪刷新"
   if(y-25>140){
     fill(circleColor);
     ellipse(x,y,size*10,size*10);
     x1=x;y1=y;
   }
 }
}

Flower_class:

class Flower {
  PImage flower;  //载入花朵图片
  float x,y;
  Flower(float mx, float my){
    x=mx;
    y=my;
    flower = loadImage("flower.png");  //载入花朵图片
  }
  void show(){
    if(flowerSize<200){
      flowerSize+=10;
      if((mouseY-flowerSize/2)>120){
        image(flower, x-flowerSize/2, y-flowerSize/2,flowerSize,flowerSize);
      }
    }
  }
}

接下去是这个项目所需的一些图片资源:
全部项目资源可从这里下载:processing趣味画板代码及资源
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/zhulong16/article/details/99688786