processing实现动态和交互-屁民科普
先来说说手绘和码绘的区别
手绘作品:很久之前画的了(我大索隆
手绘与码绘技法的比较
手绘:先绘制出大体的轮廓草稿,然后再细致的绘制,如果在绘画的时候
码绘:随时可以删改,并且非常方便,颜色可随意调配
如果是手绘还是在纸上画的,想要修改颜色可不是那么容易,可能上错了颜色,整个作品就会白做了。忽然想到学建筑的同学给工图描边
编程实现
一开始看了很多的例子,寻找灵感,做了几个小尝试
(因为博主不太会搞动态图,所以这些交互的部分,没有办法看动图233,所以就贴了个图,有点丑陋,想看效果的可以把代码复制,自己运行看看)
尝试1
实现小球围绕鼠标旋转,鼠标点击后,会消失,但实际上我不想做这种效果,还没有改进。因为里面的小球在高速旋转,所以截图太丑了555
还有拖尾的效果,主要的函数是这个
v[i].lerp(mouseX+cos(theta[i])*(rnew[i]),mouseY+sin(theta[i])*(rnew[i]),0,easing[i]);
/*realize circle orbit*/
//10 circles orbit around the center
//(mouseX,mouseY)is center circles radius different
int num=300;//the number of the circles
int max_r=110;//max orbit radius
int orbit_range=round(random(50,60));//set orbit range
PVector v[]=new PVector[num];//circles' pos
float n[]=new float[num];//circles
float theta[]=new float[num];//rotate angle
float rnew[]=new float[num];//a new circle's orbit radius
float r[]=new float[num];//a circle's radius
float theta_gap[]=new float[num];//set a circle's orbit theta
float easing[]=new float[num];
color c[]=new color[num];//each circle's color
boolean mouse_tag=true;//if key pressed tag=false
void setup()
{
// colorMode(HSB,180,100,255);
size(600,600);//set a canvan
for (int i=1;i<=num-1;i++)
{
//r[i]=random(1,5);//set circles' radius
c[i]=color(random(100,200),255,random(180,255));//set color random
rnew[i]=round(i/100)*(orbit_range/(round(num/100)-1))+(max_r-orbit_range);//one orbit has num/10 circles
theta[i]=random(360)*PI/180;//set original circle's theta
theta_gap[i]=random(72/PI);// set translate theta
// v[i] = new PVector(mouseX+cos(theta[i])*rnew[i],mouseY+sin(theta[i])*rnew[i]);//set a circle's pos
v[i] = new PVector(mouseX+cos(theta[i])*rnew[i],mouseY+sin(theta[i])*rnew[i]);//set a circle's pos
easing[i]=random(0.015,0.7);
//easing[i]=random(0.02,0.3);
}
frameRate(60);
smooth();
}
void draw()
{
fill(0,0,0);
rect(0,0,width,height);
// pushMatrix();
noStroke();
if(mouse_tag)
{
for (int i=1; i<=num-1;i++)
{
r[i]=random(1,5);
fill(c[i]);
theta[i]+=theta_gap[i];
//translate(mouseX,mouseY);
// rotate(theta[i]);
v[i].lerp(mouseX+cos(theta[i])*(rnew[i]),mouseY+sin(theta[i])*(rnew[i]),0,easing[i]);
ellipse(v[i].x, v[i].y, r[i],r[i]);
}
//popMatrix();
}
//pressed mouse
if(!mouse_tag)
{
for(int i=1;i<=num-1;i++)
{
theta[i]+=theta_gap[i];
r[i]=random(10,20);//set pressed circles radius
rotate(theta[i]);
//translate(mouseX+cos(theta[i]),mouseY+(theta_gap[i]));
v[i].lerp(mouseX+cos(theta[i]),mouseY+sin(theta[i]),0,easing[i]);
ellipse(v[i].x,v[i].y,r[i],r[i]);
}
}
}
void mousePressed()
{
mouse_tag=!mouse_tag;
}
但后来给同学看,他们非要说我这个像一堆苍蝇,我就再也不想直视他了。。。
尝试2
实现一个类似于星星的连线,可以鼠标移动的位置,距离在60以内就会自己连接起来。
以下是完整代码
//create points dis between them
//first create points
int num=100;
float r[]=new float[num];//set points radius
float theta[]=new float[num];
//float theta=30;
PVector v[]=new PVector[num];//random vector
float dst[]=new float[num];//distacne between the point and the mouse
float dst1[]=new float[num];//points between together
float[] easing=new float[num];
float move_dist;
boolean mo=true;//if mouse pressed
void setup()
{
size(600,600);
// theta=30;
for(int i=1;i<=num-1;i++)
{
v[i]=new PVector(random(width),random(height));//set points pos
r[i]=random(1,5);//set points radius
move_dist=random(20,40);
theta[i]=random(180)*PI/180;
easing[i]=random(0.06,0.9);
}
frameRate(30);
}
void draw()
{
background(0,0,0);
fill(255,255,255);
for(int i=1;i<=num-1;i++)
{
v[i]=new PVector(v[i].x+cos(second()+random(20,30))+random(-1,1),v[i].y+sin(second()+random(20,30))+random(-1,1));//set points pos
//r[i]=random(1,5);//set points radius
}
for (int i=1;i<=num-1;i++)
{
noStroke();
ellipse(v[i].x,v[i].y,r[i],r[i]);
dst[i]=dist(mouseX,mouseY,v[i].x,v[i].y);
for(int j=1;j<=num-1;j++)
{
if(dst[j]<=60)
{
stroke(255,255,255);
stroke(255,255-dst[j]);
strokeWeight(1);
line(mouseX,mouseY,v[j].x,v[j].y);
}
}
if(mo)
{
for (int j=1;j<=num-1;j++)
{
dst1[j]=dist(v[i].x,v[i].y,v[j].x,v[j].y);
if(dst1[j]<=60)
{
stroke(255,255,255);
stroke(255,255-dst[j]);
strokeWeight(1);
line(v[i].x,v[i].y,v[j].x,v[j].y);
}
}
if(!mo)
{
for(int k=1;k<=num-1;k++)
{
v[k].lerp(mouseX+cos(theta[k]),mouseY+sin(theta[k]),0,easing[k]);
}
}
}
}
}
void mousePressed()
{
mo=!mo;
}
做了这些尝试之后,有了想法?打算做一个小游戏,所以初步制作了一个封面。
介绍一下这里的图片是什么意思,一开始我想做一个剪影的图,类似于万圣节的感觉,像这样
后来比较懒,不想一个一个点的画了,所以就绘制了简单的矩形,作为“树”。他的坐标是随机生成的,宽度也是在一定范围内随机的,确定了他的高度。树分成两种颜色,当作中景和后景。后面的树颜色浅(back trees),中间的是深色(middle trees)
ps:这里定义变量的部分我没贴上去,后面会发完整的代码,需要的同学继续往后看。
c_t[i]=color(234,230,255);
t_tree[i]=new PVector(random(width),0);
t_width[i]=random(5,8);
m_width[i]=random(5,20);
void draw_tree()
{
translate(second(),0);
//back trees
for(int i=0;i<=num-2;i++)
{
t_height[i]=win_length;
fill(c_t[i]);
rect(t_tree[i].x,t_tree[i].y,t_width[i],t_height[i]);
}
//middle trees
for(int i=0;i<=20;i++)
{
t_height[i]=win_length;
fill(c_m[i]);
rect(t_tree[i].x,t_tree[i].y,m_width[i],t_height[i]);
}
for(int i=0;i<=10;i++)
{
t_height[i]=win_length;
fill(232,172,288);
rect(t_tree[i].x,t_tree[i].y,m_width[i],t_height[i]);
}
}
树叶的部分是用椭圆绘制的,坐标也是随机的
c_t[i]=color(234,230,255);
c_m[i]=color(230,219,255);
leafb_width[i]=random(70,90);
leafb_length[i]=random(170,190);
leaff_width[i]=random(120,140);
leaff_length[i]=random(100,120);
void draw_leaf()
{
for(int i=0;i<=num-2;i++)
{
fill(c_t[i]);
ellipse(leaf_b[i].x,leaf_b[i].y,leafb_width[i],leafb_length[i]);
fill(c_m[i]);
ellipse(leaf_b[i].x+10,leaf_b[i].y,leaff_width[i]+5,leaff_length[i]);
}
}
路的部分
hill_width[i]=random(width/4,width/3);
hill_length[i]=random(100,200);
void draw_hill()
{
//back_hill
for (int i=0;i<=4;i++)
{
fill(c_t[i]);
ellipse(hill[i].x+200,hill[i].y+10,hill_width[i],hill_length[i]+10);
}
//front_hill
for (int i=0;i<=4;i++)
{
fill(c_h[i]);
ellipse(hill[i].x,hill[i].y,hill_width[i],hill_length[i]);
}
for (int i=0;i<=10;i++)
{
fill(232,166,197);
ellipse(hill[i].x+50,hill[i].y+40,hill_width[i],hill_length[i]);
}
}
void draw_road()
{
fill(232,166,197);
rect(-100,height*1/2,width+100,200);
fill(232,155,198);
rect(-100,height*1/2+20,width+100,100);
for (int i=0;i<=8;i++)
{
fill(232,155,198);
ellipse(hill[i].x+20,hill[i].y+70,hill_width[i],hill_length[i]);
}
fill(215,158,232);
rect(-100,height*1/2+50,width+100,100);
for (int i=0;i<=8;i++)
{
fill(215,158,232);
ellipse(hill[i].x+50,hill[i].y+100,hill_width[i]-30,hill_length[i]-30);
}
}
窗户形状的部分
void draw_wind()
{
v[0]=new PVector(0,height*1/3);
v[1]=new PVector(width/4,0);
v[2]=new PVector(width*3/4,0);
fill(232,198,178);
rect(v[0].x-100,v[0].y,width+100,win_width);
rect(v[1].x,v[1].y,win_width,win_length);
rect(v[2].x-win_width,v[2].y,win_width,win_length);
}
鼠标点击之后,是这幅图
有没有很熟悉,对我的背景换成了我那个动态的星座,那些星星会颤抖233,鼠标移动过去还是会连线。
这个切换实现起来也很简单,设置一个布尔变量作为判断的标签,如果按下鼠标就把背景换成星座。
另外我的鼠标的效果也添加了进去,对就是那个同学说长得像苍蝇的鼠标效果。
再次点击还能切换回白天模式。
现在就贴出全部代码
PVector q[]=new PVector[150];//random vector
float dst[]=new float[150];//distacne between the point and the mouse
float dst1[]=new float[150];//points between together
float move_dist;
boolean mo=true;//if mouse pressed
//float r[]=new float[150];//a circle's radius
/*realize circle orbit*/
//10 circles orbit around the center
//(mouseX,mouseY)is center circles radius different
int aa=1000;//the number of the circles
int max_r=150;//max orbit radius
int orbit_range=round(random(50,60));//set orbit range
PVector p[]=new PVector[aa];//circles' pos
float n[]=new float[aa];//circles
float theta[]=new float[aa];//rotate angle
float rnew[]=new float[aa];//a new circle's orbit radius
float r[]=new float[aa];//a circle's radius
float theta_gap[]=new float[aa];//set a circle's orbit theta
float easing[]=new float[aa];
color c[]=new color[aa];//each circle's color
boolean mouse_tag=true;//if key pressed tag=false
PVector v[]=new PVector[3];
float x1=-1,y1=500;//curve start point
float x2=599,y2=500;//curve end point
float cx1=300,cy1=300,cx2=300,cy2=300;//ensure the shape of the curve
float cx3=300,cy3=300,cx4=300,cy4=300;//ensure the shape of the curve
int num=int(random(50,60));
int b_num=10;//branch_num
float win_width,win_length;//set win properties
//float[] tall_t=new float[num]; //obj tall tree
PVector t_tree[]=new PVector[num];//pos tall tree
PVector t_bran[]=new PVector[num];//pos branch
PVector leaf_b[]=new PVector[num];// background tree leaves pos
PVector hill[]=new PVector[num];//hill
PVector leaves[]=new PVector[num];//small leaves
float[] t_width=new float[num];//tree properties
float[] t_height=new float[num];
color c_t[]=new color[num];//color tall
float[] m_width=new float[num];//middle tree
color c_m[]=new color[num];//color middle
float[] leafb_width=new float[num];
float[] leafb_length=new float[num];
float[] leaff_width=new float[num];
float[] leaff_length=new float[num];
float[] hill_width=new float[num];
float[] hill_length=new float[num];
color c_h[]=new color[num];//color hill
float[] leaves_c=new float[num];
float[] speed=new float[num];
float radius=5;
void setup()
{
//star
for (int i=1;i<=149;i++)
{
q[i]=new PVector(random(width),random(height));//set points pos
move_dist=random(20,40);
}
//mouse
for (int i=1;i<=aa-1;i++)
{
r[i]=random(1,5);//set circles' radius
c[i]=color(230,229,113);//set color random
rnew[i]=round(i/100)*(orbit_range/(round(aa/100)-1))+(max_r-orbit_range);//one orbit has num/10 circles
theta[i]=random(360)*PI/180;//set original circle's theta
theta_gap[i]=random(72/PI);// set translate theta
// v[i] = new PVector(mouseX+cos(theta[i])*rnew[i],mouseY+sin(theta[i])*rnew[i]);//set a circle's pos
p[i] = new PVector(mouseX+cos(theta[i])*rnew[i],mouseY+sin(theta[i])*rnew[i]);//set a circle's pos
easing[i]=random(0.015,0.7);
//easing[i]=random(0.02,0.3);
}
frameRate(60);
smooth();
//bg
size(900,600);
for(int i=0;i<=num-1;i++)
{
c_t[i]=color(234,230,255);
c_m[i]=color(230,219,255);
c_h[i]=color(230,216,255);
win_width=30;
win_length=width/3;
t_tree[i]=new PVector(random(width),0);
leaf_b[i]=new PVector(random(width),random(0,30));
hill[i]=new PVector(random(width),win_length);
leaves[i]=new PVector(random(width),random(30,width/4));
t_width[i]=random(5,8);
m_width[i]=random(5,20);
leafb_width[i]=random(70,90);
leafb_length[i]=random(170,190);
leaff_width[i]=random(120,140);
leaff_length[i]=random(100,120);
hill_width[i]=random(width/4,width/3);
hill_length[i]=random(100,200);
leaves_c[i]=random(20,30);
}
}
//no
void draw_wind()
{
v[0]=new PVector(0,height*1/3);
v[1]=new PVector(width/4,0);
v[2]=new PVector(width*3/4,0);
fill(232,198,178);
rect(v[0].x-100,v[0].y,width+100,win_width);
rect(v[1].x,v[1].y,win_width,win_length);
rect(v[2].x-win_width,v[2].y,win_width,win_length);
}
void draw_tree()
{
translate(second(),0);
//back trees
for(int i=0;i<=num-2;i++)
{
t_height[i]=win_length;
fill(c_t[i]);
rect(t_tree[i].x,t_tree[i].y,t_width[i],t_height[i]);
}
//middle trees
for(int i=0;i<=20;i++)
{
t_height[i]=win_length;
fill(c_m[i]);
rect(t_tree[i].x,t_tree[i].y,m_width[i],t_height[i]);
}
for(int i=0;i<=10;i++)
{
t_height[i]=win_length;
fill(232,172,288);
rect(t_tree[i].x,t_tree[i].y,m_width[i],t_height[i]);
}
}
void draw_leaf()
{
for(int i=0;i<=num-2;i++)
{
fill(c_t[i]);
ellipse(leaf_b[i].x,leaf_b[i].y,leafb_width[i],leafb_length[i]);
fill(c_m[i]);
ellipse(leaf_b[i].x+10,leaf_b[i].y,leaff_width[i]+5,leaff_length[i]);
}
}
void draw_leaves()
{
for(int i=0;i<=30;i++)
{
fill(c_m[i]);
ellipse(leaves[i].x,leaves[i].y,leaves_c[i],leaves_c[i]);
}
}
void draw_hill()
{
//back_hill
for (int i=0;i<=4;i++)
{
fill(c_t[i]);
ellipse(hill[i].x+200,hill[i].y+10,hill_width[i],hill_length[i]+10);
}
//front_hill
for (int i=0;i<=4;i++)
{
fill(c_h[i]);
ellipse(hill[i].x,hill[i].y,hill_width[i],hill_length[i]);
}
for (int i=0;i<=10;i++)
{
fill(232,166,197);
ellipse(hill[i].x+50,hill[i].y+40,hill_width[i],hill_length[i]);
}
}
void draw_road()
{
fill(232,166,197);
rect(-100,height*1/2,width+100,200);
fill(232,155,198);
rect(-100,height*1/2+20,width+100,100);
for (int i=0;i<=8;i++)
{
fill(232,155,198);
ellipse(hill[i].x+20,hill[i].y+70,hill_width[i],hill_length[i]);
}
fill(215,158,232);
rect(-100,height*1/2+50,width+100,100);
for (int i=0;i<=8;i++)
{
fill(215,158,232);
ellipse(hill[i].x+50,hill[i].y+100,hill_width[i]-30,hill_length[i]-30);
}
}
void draw_bg()
{
fill(0,0,0);
rect(0,0,width,height);
fill(255,255,255);
for(int i=1;i<=149;i++)
{
q[i]=new PVector(q[i].x+cos(second()+random(20,30))+random(-1,1),q[i].y+sin(second()+random(20,30))+random(-1,1));//set points pos
}
for (int i=1;i<=149;i++)
{
noStroke();
ellipse(q[i].x,q[i].y,5,5);
dst[i]=dist(mouseX,mouseY,q[i].x,q[i].y);
for(int j=1;j<=num-1;j++)
{
if(dst[j]<=200)
{
stroke(255,255,255);
stroke(255,255-dst[j]);
//strokeWeight(1);
//line(mouseX,mouseY,q[j].x,q[j].y);
}
}
for (int j=1;j<=num-1;j++)
{
dst1[j]=dist(q[i].x,q[i].y,q[j].x,q[j].y);
if(dst1[j]<=100)
{
stroke(255,255,255);
stroke(255,255-dst[j]);
strokeWeight(1);
line(q[i].x,q[i].y,q[j].x,q[j].y);
}
}
}
}
void draw()
{
background(238,239,255);
noStroke();
if (mo)
{ draw_tree();
draw_leaf();
draw_leaves();
draw_hill();
draw_road();
draw_wind();}
if(!(mo))
{
draw_bg();
draw_tree();
draw_leaf();
draw_leaves();
draw_hill();
draw_road();
}
for (int i=1; i<=num-1;i++)
{
fill(c[i]);
theta[i]+=theta_gap[i];
p[i].lerp(mouseX+cos(theta[i])*(rnew[i]),mouseY+sin(theta[i])*(rnew[i]),0,easing[i]);
ellipse(p[i].x, p[i].y, r[i],r[i]);
}
}
void mousePressed()
{
mo=!mo;
}
网站推荐:
这里面有很多人编辑的代码和例子,有demo视频可以查看,网站的界面我也超级喜欢
https://www.openprocessing.org
这个网址一上来的界面就很炫
http://iprocessing.cn
这个网址嘛,就是很多人的创意啦(手动滑稽
https://shimo.im/sheet/NqhjMXJG9sMl4qaP/RIDOC/