文章目录
- [processing 官网链接](https://processing.org/)
- **rect()函数**
- **ellipse()函数**
- **fill()函数**
- **stroke()函数**
- **noStroke()函数**
- **beginShape()**
- **setup()函数**
- **draw()函数**
- **line()函数**
- **strokeWeight()函数**
- **alpha相关**
- **变量的类型**
- **鼠标交互**
- **键盘交互**
- **鼠标水平滑动改变小球颜色**
- **使白色矩形重复平移**
- **加载图片并显示**
- **图片跟随鼠标移动**
- **实现重影叠加效果。**
- **贝塞尔曲线**
- **贝塞尔曲线**
- **音频播放**
- **音频停止与回放**
- **声音强度**
- **声音交互**
- **声音控制方块人的嘴巴动**
- **播放多个音频文件**
- **用麦克风录音存储为wav格式**
- **数据映射**
- **用for循环创造艺术图像**
- **随机数**
- **arrays数组**
- **println相关**
- **process标签页**
- **用函数来输出一个渐变色图案**
- **定时器**
- **P3D渲染器**
- **将当前变换矩阵嵌入和弹出矩阵堆栈。**
- **绘制立方体**
- **球体**
- **定向光**
- **环境光**
- **自定义3D图形**
- **加载视频**
- **读取摄像头**
- **调整摄像头影像的尺寸**
- **获取颜色信息**
- **读写像素点**
- **视频输出像素点风格**
- **像素块风格**
- **视频替代摄像头画面**
- **粒子系统**
- **完成鼠标靠近粒子 颜色改变的效果**
- **点击鼠标粒子都靠近鼠标点击位置**
- **爆炸的像素**
- **粒子连线**
- **controlP5库 Gui Button**
- **controlP5库 Gui Slider**
- **在粒子连线中加入UI**
- **绘制椭圆**
- **noise随机数**
- **利用sin()函数绘图**
**
processing 官网链接
**
void setup()
{
}
void draw()
{
}
setup 是放置启动这个程序时用到的代码
draw是需要持续运行的代码
运行后出现的窗口默认是100X100像素
void setup()
{
size(800,600);
}
void draw()
{
}
size(a,b);内输入两个数值代表像素点,是改变窗口大小的命令。
void setup()
{
size(800,600);
}
void draw()
{
background(255,255,255);
}
background(a,b,c);输入三个0到255代表红,绿,蓝RGB的数值,是窗口背景颜色的命令。
background(a);输入一个数字的时候,相当于重复三次这个数字。
如果不知道想要颜色的RGB具体的数值,在工具(Tools)颜色选择器(Color Selector)中找。
rect()函数
rect(a,b,c,d)绘制矩形命令;输入四个数值,第一个数值是从左到右X轴,第二个数值从上到下Y轴,第三个数值矩形的宽(Width),第四个数值矩形的高(Height)。
ellipse()函数
ellipse(a,b,c,d);在屏幕上绘制一个椭圆(椭圆形)。宽度和高度相等的椭圆是一个圆。默认情况下,前两个参数设置位置,第三个和第四个参数设置形状的宽度和高度。
fill()函数
fill();设置用于填充形状的颜色。例如,如果运行fill(204,102,0),则所有后续形状都将用橙色填充。
stroke()函数
stroke(a,b,c);设置用于在形状周围绘制线条和边框的颜色。根据当前的colorMode(),可以根据RGB或HSB颜色指定该颜色。默认颜色空间是RGB,每个值的范围都在0到255之间.
红色的矩形在绿色的上面,因为程序按照顺序执行,红色矩形是最后绘制的所以会在绿色矩形之上。
background()放在绘制绿色矩形与红色矩形中间后,绿色矩形不显示是因为先绘制绿色矩形后background函数设置了白色背景将绿色矩形覆盖掉了。
noStroke()函数
noStroke();禁用绘制笔划(轮廓)。如果同时调用noStroke()和noFill(),则不会在屏幕上绘制任何内容。
beginShape()
使用beginShape()和endShape()函数可以创建更复杂的表单。beginShape()开始记录形状的顶点,endShape()停止记录。kind参数的值告诉它要从提供的顶点创建哪些形状的形状。如果未指定模式,则形状可以是任何不规则多边形。
beginShape()可用的参数是POINTS,LINES,TRIANGLES,TRIANGLE_FAN,TRIANGLE_STRIP,QUADS和QUAD_STRIP。调用beginShape()函数后,必须遵循一系列vertex()命令。要停止绘制形状,请调用endShape()。该顶点()具有两个参数的函数指定2D位置,具有三个参数的vertex()函数指定3D位置。每个形状都会用当前的笔触颜色勾勒出轮廓,并用填充颜色填充。
setup()函数
setup函数在运行后执行一次;
draw()函数
draw函数永远循环,直到停止
line()函数
line(x1,y1,x2,y2)在屏幕上画一条线(两点之间的直接路径)。前两个值是第一个点的坐标,后两个值是第二个点的坐标。要为线条着色,请使用stroke()函数。无法填充线条,因此fill()函数不会影响线条的颜色。
strokeWeight()函数
strokeWeight()设置用于线条,点和形状周围边框的笔划宽度。所有宽度均以像素为单位设置。
alpha相关
fill(a,b,c,d)函数的d值可改变填充颜色的透明度0到255之间。
stroke(a,b,c,d)函数的d值可改变填充颜色的透明度0到255之间。数值越小透明度就越高。
变量的类型
与其他编程语言一样都有变量才存储数据。
boolean 布尔值true和false的数据类型。通常将布尔值与控制语句一起使用来确定程序的流程。
byte 字节的数据类型,信息的8位存储从127到-128的数值。字节是一种方便的数据类型,用于与串行端口之间来回发送信息,并以比char数据类型更简单的格式表示字母。
char字符数据类型,每个字符的长度为两个字节(16位),并用单引号引起来来区分。
color用于存储颜色值的数据类型。颜色可以使用get()和color()进行分配,也可以直接使用十六进制表示法(例如#FFCC00或0xFFFFCC00 )指定颜色。
float 使用32位存储浮点数的数据类型,例如,带小数点的数字。
double 双精度浮点型,比单精度存储范围更大,使用64位存储一个浮点数。
int 存储整型的数据类型。整数可以大至2,147,483,647,低至-2,147,483,648(存储为32位)
long 长整型。长整数的最小值为-9,223,372,036,854,775,808,最大值为9,223,372,036,854,775,807(存储为64位)。
变量的调用只能在一个函数中,在哪里申明在哪里调用。可以在setup函数上声明。
鼠标交互
int RectSize =30;
void setup()
{
size(400,400);
}
void draw()
{
background(mouseX,125,125);
rect(mouseX,100,RectSize,RectSize);
}
void mousePressed()
{
println(mouseX+""+mouseY);
RectSize =100;
}
mouseX与mouseY分别是鼠标的x,y轴坐标。在Processing是封装好的预制变量可以直接用。
void mousePressed(){ } 按下鼠标按钮每次之后函数被调用。鼠标和键盘事件仅在程序具有draw()时起作用。如果没有draw(),则代码仅运行一次,然后停止侦听事件。
键盘交互
int x = 0;
void setup()
{
size(400,400);
}
void draw()
{
background(125,125,125);
rect(x,0,50,50);
}
void keyPressed()
{
if(key == 'd')
{
x+=5;
}
if(key == 'a')
{
x-=5;
}
}
利用if语句在keyProcessed函数中判断输入的key值。
鼠标水平滑动改变小球颜色
void setup()
{
size(400,400);
}
void draw()
{
background(125,125,125);
if(mouseX>width/2)
{
fill(255,0,0);
}
else
{
fill(0,0,255);
}
ellipse(180,180,100,100);
}
使白色矩形重复平移
int Xpostion=0;
void setup()
{
size(400,400);
}
void draw()
{
background(0,0,0);
rect(Xpostion,0,100,100);
Xpostion+=3;
if(Xpostion>width)
{
Xpostion=0;
}
}
width是processing默认的满屏幕像素宽,同理height是满屏像素的高。
加载图片并显示
PImage类,用于存储图像的数据类型。处理可以显示.gif,.jpg,.tga和.png图像。图像可以显示在2D和3D空间中。在使用图像之前,必须使用loadImage()函数加载该图像。
loadImage(),将图像加载到PImage类型的变量中。可以加载四种类型的图像(.gif,.jpg,.tga,.png)图像。为了正确加载,图像必须位于当前草图的数据目录中。
**image()**将图像显示在窗口的函数。
图片跟随鼠标移动
mouseX与mouseY分别是鼠标的x,y轴坐标。将鼠标坐标替换成图片位置坐标每次刷新就实现了图片跟随图片效果,也可以把鼠标坐标替换成图片大小的数值,图片大小就会跟随鼠标移动而变化大小。
例子:让一条线跟着鼠标动。
void draw()
{
background(204);
line(mouseX, 20, mouseX, 80);
}
实现重影叠加效果。
将background()函数注释掉。背景不会被清除,实现了重影拖尾的效果。
贝塞尔曲线
noFIll()禁用填充几何。如果同时调用noStroke()和noFill(),则不会在屏幕上绘制任何内容。
bezier(x1,y1,x2,y2,x3,y3,x4,y4)贝塞尔曲线函数,这些曲线由一系列锚点和控制点定义。前两个参数指定第一个锚点(起始点位置),后两个参数指定另一个锚点(终点位置)。中间参数指定控制点,这些控制点定义曲线的形状。贝济耶曲线由法国工程师皮埃尔·贝济耶(Pierre Bezier)开发。
贝塞尔曲线
noFIll()禁用填充几何。如果同时调用noStroke()和noFill(),则不会在屏幕上绘制任何内容。
bezier(x1,y1,x2,y2,x3,y3,x4,y4)贝塞尔曲线函数,这些曲线由一系列锚点和控制点定义。前两个参数指定第一个锚点(起始点位置),后两个参数指定另一个锚点(终点位置)。中间参数指定控制点,这些控制点定义曲线的形状。
贝济耶曲线由法国工程师皮埃尔·贝济耶(Pierre Bezier)开发。
音频播放
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;
Minim min;
AudioPlayer song;
void setup()
{
size(400,400);
min =new Minim(this);
song =min.loadFile("paoxiao.wav",2048);
//song.play();
song.loop();
}
void draw()
{
}
将要播放的音频放在程序目录下的data文件中。
想要播放声音需要调用Minim音频库。
**song.play()**播放一次;
**song.loop()**循环播放;
以下是Minim的一些功能:
AudioPlayer:WAV,AIFF,AU,SND和MP3文件的单声道和立体声播放。
AudioMetaData:填充了有关文件的元数据的对象,例如ID3标签。
AudioRecorder:单声道和立体声音频记录,可以缓冲或直接到磁盘。
AudioInput:单声道和立体声输入监视。
AudioOutput:单声道和立体声声音合成。
FFT:对音频数据执行傅立叶变换以生成频谱。
BeatDetect:用于进行节拍检测的类。
音频停止与回放
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;
Minim min;
AudioPlayer song;
void setup()
{
size(400,400);
min =new Minim(this);
song =min.loadFile("onepiece.mp3",2048);
song.loop();
}
void draw()
{
}
void keyPressed()
{
if(key ==' ')
{
song.pause();
}
if(key =='d')
{
song.play();
}
if(key=='a')
{
song.rewind();
song.play();
}
}
pause(),暂停;
rewind(),倒回重新开始。这不会停止播放。
声音强度
利用声音强度做一个音画互动程序。
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;
Minim min;
AudioPlayer song;
void setup()
{
size(600,600);
min =new Minim(this);
song =min.loadFile("onepiece.mp3",2048);
song.loop();
}
void draw()
{
float backfroundCol =song.mix.level()*255.0*10;
background(backfroundCol,backfroundCol,backfroundCol);
float rectsize =song.mix.level()*150.0;
fill(rectsize,0,rectsize,125);
rect(200,200,rectsize*10,rectsize*10);
}
mix.level(),任意给定时间点的音量,是一个浮点数在0和1之间。0表示静音,1表示最大声音。
mix表示混音。left.level().表示左声道,right.level().表示右声道。
将音量的值传入background中就能根据声音大小来改变背景颜色。
声音交互
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;
Minim minim ;
AudioInput microphone;
void setup()
{
size(400,400);
minim =new Minim(this);
microphone =minim.getLineIn();
}
void draw()
{
float backgroundCol =microphone.mix.level()*255.0*10.0;
background(backgroundCol,backgroundCol,backgroundCol);
float rectsize =microphone.mix.level()*255.0;
rect(200,200,rectsize,rectsize*10);
}
microphone =minim.getLineIn();
这段代码会开始调用电脑上的麦克风来采集声音。
声音控制方块人的嘴巴动
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;
Minim minim ;
AudioInput microphone;
void setup()
{
size(500,500);
minim =new Minim(this);
microphone =minim.getLineIn();
}
void draw()
{
background(0,0,0);
ellipse(100,100,50,50);
ellipse(400,100,50,50);
float mouthOpen =microphone.mix.level()*100.0;
rect(100,300,300,mouthOpen);
}
播放多个音频文件
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;
Minim minim ;
AudioPlayer tiger;
AudioPlayer fox;
AudioPlayer dragon;
void setup()
{
size(500,500);
minim =new Minim(this);
tiger =minim.loadFile("tiger.mp3");
fox =minim.loadFile("fox.mp3");
dragon =minim.loadFile("dragon.mp3");
}
void draw()
{
background(0,0,0);
}
void keyPressed()
{
if(key=='a')
{
tiger.rewind();
tiger.play();
}
if(key=='s')
{
fox.rewind();
fox.play();
}
if(key=='d')
{
dragon.rewind();
dragon.play();
}
}
可以加载不同的声音做一个鼓机或者模拟钢琴之类的程序。
不加rewind(),再按下指令键就不会重新播放声音。
用麦克风录音存储为wav格式
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;
Minim minim;
AudioInput microphone;
AudioRecorder record;
void setup()
{
size(500,500);
minim =new Minim(this);
microphone =minim.getLineIn();
record =minim.createRecorder(microphone,"time.wav");
}
void draw()
{
background(0,0,0);
}
void keyPressed()
{
if(key=='a')
{
record.beginRecord();
}
if(key=='s')
{
record.endRecord();
record.save();
}
}
三个对象分别是minim音频扩展库,麦克风对象,录音机对象。
设定麦克风变量microphone =minim.getLineIn();
设定录音机对象record =minim.createRecorder();然后将麦克风数据传入录音机函数中。
beginRecord();开始录音
endRecord();结束录音
save();保存
数据映射
void setup()
{
size(500,500);
}
void draw()
{
background(0,0,0);
float rectWith =map(mouseX,0,width,0,100);
rect(0,0,rectWith,20);
}
map(a,b,c,d,e);将数字从一个范围重新映射到另一个范围。
map接收五个数值,a数值就是需要转换的数字 b和c是第一个数值所属的最小和最大值,d和e是赋予的a新的区间。
用for循环创造艺术图像
void setup()
{
size(500,500);
}
void draw()
{
background(0,0,0);
noStroke();
for(int i =width;i>0;i-=20)
{
fill(i/2,i/2,i/2);
rect(width/2-i/2,height/2-i/2,i,i);
}
}
随机数
void setup()
{
size(500,500);
}
void draw()
{
background(125,125,125);
for(int i =0; i<5;i++)
{
float randX =random(0,width);
float randY =random(0,height);
fill(255,0,255);
rect(randX,randY,40,40);
}
}
方块的位置是随机数。
arrays数组
int [] backgroundColors =new int [3];
void setup()
{
size(500,500);
backgroundColors[0] =(int)random(0,255);
backgroundColors[1] =(int)random(0,255);
backgroundColors[2] =(int)random(0,255);
String [] names ={"wang","pu","qing"};
println(names[(int)random(0,2)]);
}
void draw()
{
background(backgroundColors[0],backgroundColors[1],backgroundColors[2]);
}
数组与随机数的小练习
直接在println()函数中输入数组名就可以输出数组。
println相关
void setup()
{
size(500,500);
int [] Arraynum ={0,34,128,2};
int num1 =1;
int num2=11;
println(Arraynum);
println("array:"+Arraynum);
println(num1,num2);
println(num1+" "+num2);
}
void draw()
{
background(0,0,0);
}
println(num1,num2);
println(num1+" "+num2);
相同效果。
println(数组名)会显示所有的数组
println(“array:”+数组)会显示内存指针(地址)
process标签页
可以把一些程序写在其他的标签页中,要用的时候调用就可以了。
用函数来输出一个渐变色图案
void setup()
{
size(800,800);
}
void draw()
{
background(0,0,0);
drawtarget(width/2,height/2,10,30);
drawtarget(300,150,9,30);
drawtarget(600,200,15,30);
}
void drawtarget(int posX,int posY,int numRings,int ringSize)
{
noStroke();
for(int i=numRings;i>0;i--)
{
int size =i*ringSize;
int gray =i*(255/numRings);
fill(gray,gray,gray);
ellipse(posX,posY,size,size);
}
}
定时器
使一个白色正方体在3到5秒出现一次
void setup()
{
size(400,400);
}
void draw()
{
background(0,0,0);
if(millis()>3000&&millis()<5000)
{
fill(255,255,255);
rect(width/2,height/2,100,100);
}
}
**mills()**返回开始运行当前程序时的毫秒数。
在程序开始的时候计时器开始计时,程序关闭时计时器清零。
P3D渲染器
在平面X,Y的基础上增加了一个深度值(depth)。
size(a,b,P3D);P3D没有具体的值,P3D趋近于无穷。
void setup()
{
size(400,400,P3D);
}
void draw()
{
background(125);
translate(100,100);
fill(125,0,0);
rect(0,0,100,100);
}
在2D下 translate(a,b)表示在(0,0)坐标在左移a像素,下移b像素。
通常在画3D图形时经常会用translate()将初始位置移动width/2和height/2使得屏幕中心成为(0,0)坐标。
int posZ=0;
void setup()
{
size(400,400,P3D);
}
void draw()
{
background(125);
translate(width/3,height/3,posZ);
fill(125,0,0);
rect(0,0,100,100);
posZ++;
}
z轴数值增加,图像放大。
将当前变换矩阵嵌入和弹出矩阵堆栈。
int posZ=0;
void setup()
{
size(400,400,P3D);
}
void draw()
{
background(125);
pushMatrix();
translate(width/3,height/3,posZ);
fill(125,0,0);
rotate(PI/4);
rect(0,0,100,100);
popMatrix();
fill(0,125,0);
rect(0,0,100,100);
}
pushMatrix()和popMatrix()必须成对出现。
绘制立方体
void setup()
{
size(400,400,P3D);
}
void draw()
{
background(125);
pushMatrix();
translate(width/2-50,height/2-50,-mouseX);
fill(125,0,0);
box(50.0);
popMatrix();
pushMatrix();
translate(100,100,-mouseY);
fill(0,125,0);
box(45,55,50);
popMatrix();
}
box(a);表示绘制一个边长为a立方体;
box(a,b,c)表示绘制一个长为a,宽为b,高为c。
3D图形都是基于(0,0)点开始绘制的,所以要配合translate函数使用。
绘制不同的3D图像,需要用到不同的translate移动位置需要分别放在pushMatrix,popMatrix函数里。
球体
在写这个程序的时候报错,查看错误之后才发现,size()函数中没有加P3D,以后一定要记住了。
void setup()
{
size(400,400,P3D);
}
void draw()
{
background(125);
pushMatrix();
translate(width/2,height/2,mouseX);
fill(0,255,0);
sphere(100.0);
popMatrix();
}
sphere()球体函数只有一个参数。
定向光
void setup()
{
size(400,400,P3D);
}
void draw()
{
background(0);
pushMatrix();
translate(width/2,height/2,-mouseX);
noStroke();
directionalLight(255,0,0,1,0,0);
directionalLight(0,255,0,1,1,0);
directionalLight(0,125,255,-1,0,0);
sphere(80);
popMatrix();
}
directionalLight(a,b,c,d,e,f);a,b,c是颜色的RGB值,d,e,f是x,y,z的单位向量。
添加定向光。定向光来自一个方向:直角撞击表面时会更强,而以柔和的角度撞击时会更弱。撞击表面后,定向光会在所有方向上散射。灯光需要包含在draw()中,以在循环程序中保持持久性。将它们放在循环程序的setup()中将导致它们仅在第一次循环时才起作用。
环境光
void setup()
{
size(400,400,P3D);
}
void draw()
{
background(0);
pushMatrix();
translate(width/2,height/2,-mouseX);
noStroke();
directionalLight(255,0,0,1,1,0);
ambientLight(0,125,10);
sphere(80);
popMatrix();
}
ambientLight()环境光,环境光单独使用的场景比较少,一般是在结合其他类型的光源后才会变得更加有用。
自定义3D图形
void setup()
{
size(400,400,P3D);
}
void draw()
{
background(0);
beginShape();
vertex(100,100,0);
vertex(300,300,-300);
vertex(150,350,-200);
endShape();
translate(150,200,-200);
sphere(100.0);
}
加载视频
import processing.video.*;
Movie m;
void setup()
{
size(800,600);
m =new Movie(this,"time.mov");
m.loop();
}
void draw()
{
background(0);
image(m,0,0,width,height);
}
void movieEvent(Movie m)
{
m.read();
}
将要加载的视频放到工程目录下的data文件中,引入import processing.video.*;库
movieEvent()这个方法会伴随draw()循环运行在后台读取视频。
image(img,a,b)
image(img,a,b,c,d)
img是要显示的图像,a是图像的x坐标,b是图像的y坐标,c是显示图像的宽度,d是显示图像的高度。
读取摄像头
import processing.video.*;
Capture cam;
void setup()
{
size(640,480);
String [] cameras =Capture.list();
for(int i =0;i<cameras.length;i++)
{
println(i+": "+cameras[i]);
}
cam=new Capture(this,cameras[1]);
cam.start();
}
void draw()
{
if(cam.available()==true)
{
cam.read();
}
image(cam,0,0);
}
导入import processing.video.*;库
cam.avaliable()==true它是用于判断摄像头状态的cam.read()是读取摄像头数据用的。
image.(cam,0,0)会把摄像头画面显示出来
调整摄像头影像的尺寸
image(cam,-0,0,800,640);只能调整画布的尺寸并不能改变分辨率。
可以根据在控制台的信息选择合适的分辨率,若是不知道摄像头的信息可以通过println打印出来。
println(cam.width+" "+cam.height)
获取颜色信息
int backgroundCol =color(255,0,0);
void setup()
{
size(400,400);
}
void draw()
{
background(backgroundCol);
float r =red(backgroundCol);
float b =blue(backgroundCol);
float g =green(backgroundCol);
println("red:"+r+",blue:"+b+",green:"+g);
}
读写像素点
import processing.video.*;
Capture cam;
void setup()
{
size(640,480);
String [] cameras =Capture.list();
for(int i =0;i<cameras.length;i++)
{
println(i+": "+cameras[i]);
}
cam = new Capture(this,cameras[1]);
cam.start();
}
void draw()
{
if(cam.available()==true)
{
cam.read();
}
cam.loadPixels();
int totalPixels =cam.width*cam.height;
println(totalPixels);
for(int i =0;i<totalPixels;i+=15)
{
color pixelCol =cam.pixels[i];
stroke(pixelCol);
int x =i % cam.width;
int y= i / cam.width;
point(x,y);
}
//image(cam,0,0,640,480);
}
cam.pixels[]数组包含了摄像头画面的所有像素。通过加载一个个像素点才呈现摄像头画面。
视频输出像素点风格
import processing.video.*;
Capture cam;
void setup()
{
size(640,480);
String [] cameras =Capture.list();
for(int i =0;i<cameras.length;i++)
{
println(i+": "+cameras[i]);
}
cam = new Capture(this,cameras[0]);
cam.start();
}
void draw()
{
if(cam.available()==true)
{
cam.read();
}
cam.loadPixels();
int pixelSize =20;
for( int y=0;y<cam.height;y+=pixelSize)
{
for(int x=0;x<cam.width;x+=pixelSize)
{
int camPixelPos =y*cam.width+x;
color pixCol =cam.pixels[camPixelPos];
fill(pixCol);
rect(x,y,pixelSize,pixelSize);
}
}
}
像素块风格
import processing.video.*;
Capture cam;
void setup()
{
size(1024,768,P3D);
String [] cameras =Capture.list();
for(int i =0;i<cameras.length;i++)
{
println(i+": "+cameras[i]);
}
cam = new Capture(this,cameras[1]);
cam.start();
}
void draw()
{
background(0);
if(cam.available()==true)
{
cam.read();
}
cam.loadPixels();
int pixelSize =20;
float sizeMult=1.5;
for( int y=0;y<cam.height;y+=pixelSize)
{
for(int x=0;x<cam.width;x+=pixelSize)
{
int camPixelPos =y*cam.width+x;
color pixCol =cam.pixels[camPixelPos];
float pixBrightness =255-brightness(pixCol);
fill(pixCol);
pushMatrix();
translate(x*sizeMult,y*sizeMult,pixBrightness);
box(pixBrightness*0.1);
popMatrix();
/* pushMatrix();
translate(x*sizeMult,y*sizeMult,0);
sphere(pixBrightness*0.1);
popMatrix();
*/
}
}
}
视频替代摄像头画面
import processing.video.*;
Movie m;
void setup()
{
size(640,480,P3D);
m =new Movie(this,"boom.mov");
m.loop();
}
void draw()
{
background(0);
m.loadPixels();
int pixelSize =10;
float sizeMult=1.5;
for( int y=0;y<m.height;y+=pixelSize)
{
for(int x=0;x<m.width;x+=pixelSize)
{
int camPixelPos =y*m.width+x;
color pixCol =m.pixels[camPixelPos];
float pixBrightness =255-brightness(pixCol);
fill(pixCol);
pushMatrix();
translate(x*sizeMult,y*sizeMult,pixBrightness);
box(pixBrightness*0.1);
popMatrix();
}
}
}
void movieEvent(Movie m)
{
m.read();
}
粒子系统
Particle p1;
Particle [] p;
void setup()
{
size(640,480);
p =new Particle[30];
for(int i =0;i<p.length;i++)
{
p[i] =new Particle();
}
}
void draw()
{
background(0);
for(int i =0;i<p.length;i++)
{
p[i].draw();
}
}
class Particle
class Particle
{
float xPos;
float yPos;
float size;
float speedX;
float speedY;
float col;
Particle()
{
xPos =random(0,width);
yPos =random(0,height);
speedX=random(-1,1);
speedY =random(-1,1);
size =random(10,20);
col =random(125,255);
}
void draw()
{
noStroke();
fill(col);
ellipse(xPos,yPos,size,size);
xPos += speedX;
yPos += speedY;
if(xPos<0)
{
xPos =0;
speedX = speedX * -1;
}
if(yPos<0)
{
yPos =0;
speedY = speedY * -1;
}
if(xPos>width)
{
xPos =width;
speedX =speedX * -1;
}
if(yPos>height)
{
yPos =height;
speedY = speedY * -1;
}
}
}
通过把background()方法放到setup()与draw()函数中会产生不同的效果;
将background()放在setup()函数里;
将background()放在draw()函数里;
将粒子的属性分成一个类,里面有粒子的坐标,速度,颜色,大小等。
完成鼠标靠近粒子 颜色改变的效果
修改粒子类
class Particle
{
float xPos;
float yPos;
float size;
float speedX;
float speedY;
float col;
Particle()
{
xPos =random(0,width);
yPos =random(0,height);
speedX=random(-1,1);
speedY =random(-1,1);
size =random(10,20);
col =random(125,255);
}
void draw()
{
noStroke();
fill(250,200-col,col);
ellipse(xPos,yPos,size,size);
xPos += speedX;
yPos += speedY;
if(dist(xPos,yPos,mouseX,mouseY)<40.0)
{
col=120;
}
else
{
col =255;
}
if(xPos<0)
{
xPos =0;
speedX = speedX * -1;
}
if(yPos<0)
{
yPos =0;
speedY = speedY * -1;
}
if(xPos>width)
{
xPos =width;
speedX =speedX * -1;
}
if(yPos>height)
{
yPos =height;
speedY = speedY * -1;
}
}
}
list(x1,y1,x2,y2)计算两点之间的距离,x1,y1是第初始点的坐标,x2,y2是终点的坐标。
点击鼠标粒子都靠近鼠标点击位置
class Particle
{
float xPos;
float yPos;
float size;
float speedX;
float speedY;
float col;
Particle()
{
xPos =random(0,width);
yPos =random(0,height);
speedX=random(-1,1);
speedY =random(-1,1);
size =random(10,20);
col =random(125,255);
}
void draw()
{
noStroke();
fill(250,200-col,col);
ellipse(xPos,yPos,size,size);
xPos += speedX;
yPos += speedY;
if(mousePressed)
{
float xdist =xPos - mouseX;
float ydist =yPos - mouseY;
xPos -=xdist*0.05;
yPos -=ydist*0.05;
}
if(xPos<0)
{
xPos =0;
speedX = speedX * -1;
}
if(yPos<0)
{
yPos =0;
speedY = speedY * -1;
}
if(xPos>width)
{
xPos =width;
speedX =speedX * -1;
}
if(yPos>height)
{
yPos =height;
speedY = speedY * -1;
}
}
}
mousePressed判断鼠标点击响应。
主要方法是 当鼠标被点击时粒子的坐标会加上它与鼠标的距离。
爆炸的像素
PImage img;
Pixel [] imgPixels ;
void setup()
{
size(640,480,P3D);
img =loadImage("test.png");
img.updatePixels();
imgPixels =new Pixel[img.width*img.height];
for(int y =0;y<img.height;y++)
{
for(int x =0;x<img.width;x++)
{
int pixIndx =y*img.width+x;
color c =img.pixels[pixIndx];
imgPixels[pixIndx] =new Pixel(x,y,c);
}
}
}
void draw()
{
background(0);
translate(width/2-img.width/2,height/2-img.height/2);
for(int i =0; i<imgPixels.length;i++)
{
imgPixels[i].draw();
}
}
class Pixel
{
float x,y,z;
color pixColor;
int pixelSize;
float zSpeed;
Pixel(float startX,float startY,color c)
{
x = startX;
y = startY;
z = 200;
pixelSize =1;
pixColor =c;
zSpeed =random(2,5);
}
void draw()
{
pushMatrix();
translate(x,y,z);
fill(pixColor);
noStroke();
rect(0,0,pixelSize,pixelSize);
popMatrix();
z+=zSpeed;
}
}
粒子连线
Particle [] particles;
int numParticles =50;
float maxDistance =50.0;
void setup()
{
size(800,800);
particles =new Particle[numParticles];
for(int i=0;i<particles.length;i++)
{
particles[i] =new Particle();
}
}
void draw()
{
background(0);
for(int i=0;i<particles.length;i++)
{
particles[i].update();
// fill(255,255,255);
// ellipse(particles[i].xPos,particles[i].yPos,5,5);
}
stroke(255,255,255);
for(int i =0;i<particles.length;i++)
{
for(int j =0;j<particles.length;j++)
{
if(i!=j)//display ellipse
{
if(dist(particles[i].xPos,particles[i].yPos,particles[j].xPos,particles[j].yPos)<maxDistance)
{
line(particles[i].xPos,particles[i].yPos,particles[j].xPos,particles[j].yPos);
}
}
}
}
}
class Particle
{
float xPos;
float yPos;
float xSpeed;
float ySpeed;
Particle()
{
xPos =random(0,width);
yPos =random(0,height);
xSpeed =random(-2,2);
ySpeed =random(-2,2);
}
void update()
{
xPos+=xSpeed;
yPos+=ySpeed;
if(xPos<0)
{
xPos=0;
xSpeed =-1.0*xSpeed;
}
if(yPos<0)
{
yPos=0;
ySpeed =-1.0*ySpeed;
}
if(xPos>width)
{
xPos=width;
xSpeed =-1.0*xSpeed;
}
if(yPos>height)
{
yPos=height;
ySpeed =-1.0*ySpeed;
}
}
}
想要显示粒子 可以去掉if(i!=j)的判断。
核心原理就是通过dist()函数得到两个点的距离,判断距离然后用line函数画线。
controlP5库 Gui Button
import controlP5.*;
ControlP5 gui;
float backgroundRed =0;
float backgroundBlue =0;
float backgroundGreen =0;
void setup()
{
size(640,480);
gui =new ControlP5(this);
gui.addButton("ChanegColor").setPosition(220,200).setSize(200,19);
gui.addButton("Balck").setPosition(220,250).setSize(200,19);
}
void draw()
{
background(backgroundRed,backgroundBlue,backgroundGreen);
}
public void ChanegColor()
{
backgroundRed =random(0.255);
backgroundBlue=random(0,255);
backgroundGreen =random(0,255);
}
public void Balck()
{
backgroundRed =0;
backgroundBlue=0;
backgroundGreen =0;
}
建立两个button组件,通过点击button组件改变窗口背景颜色。
controlP5库 Gui Slider
import controlP5.*;
ControlP5 gui;
Slider backgroundRedSlider;
Slider backgroundBlueSlider;
Slider backgroundGreenSlider;
void setup()
{
size(640,480);
gui =new ControlP5(this);
backgroundRedSlider =gui.addSlider("red").setPosition(220,200).setRange(0,255);
backgroundBlueSlider =gui.addSlider("blue").setPosition(220,230).setRange(0,255);
backgroundGreenSlider =gui.addSlider("green").setPosition(220,260).setRange(0,255);
}
void draw()
{
background(backgroundRedSlider.getValue(),backgroundBlueSlider.getValue(),backgroundGreenSlider.getValue());
}
getValue()获取Slider的值。
做出一个通过改变Slider值来改变背景颜色的小程序。
在粒子连线中加入UI
import controlP5.*;
Particle [] particles;
ControlP5 gui;
int numParticles =50;
float maxDistance;
Slider maxDistSlider;
Slider bgFadeSlider;
Slider speedSlider;
Slider strokeWidthSlider;
void setup()
{
size(800,800);
gui =new ControlP5(this);
maxDistSlider =gui.addSlider("maxDist").setPosition(20,20).setRange(0,300);
bgFadeSlider=gui.addSlider("fade").setPosition(20,50).setRange(0,100);
speedSlider=gui.addSlider("speed").setPosition(20,80).setRange(0,10);
strokeWidthSlider=gui.addSlider("stroke").setPosition(20,110).setRange(0,5);
gui.addButton("clearBackground").setPosition(20,135).setSize(100,20);
particles =new Particle[numParticles];
for(int i=0;i<particles.length;i++)
{
particles[i] =new Particle();
}
background(0);
}
void draw()
{
// background(0);
maxDistance =maxDistSlider.getValue();
noStroke();
fill(0,0,0,bgFadeSlider.getValue());
rect(0,0,width,height);
for(int i=0;i<particles.length;i++)
{
particles[i].update(speedSlider.getValue());
// fill(255,255,255);
// ellipse(particles[i].xPos,particles[i].yPos,5,5);
}
stroke(255,255,255);
strokeWeight(strokeWidthSlider.getValue());
for(int i =0;i<particles.length;i++)
{
for(int j =0;j<particles.length;j++)
{
if(i!=j)//display ellipse
{
if(dist(particles[i].xPos,particles[i].yPos,particles[j].xPos,particles[j].yPos)<maxDistance)
{
line(particles[i].xPos,particles[i].yPos,particles[j].xPos,particles[j].yPos);
}
}
}
}
}
class Particle
{
float xPos;
float yPos;
float xSpeed;
float ySpeed;
Particle()
{
xPos =random(0,width);
yPos =random(0,height);
xSpeed =random(-1,1);
ySpeed =random(-1,1);
}
void update(float speedMult)
{
xPos+=xSpeed*speedMult;
yPos+=ySpeed*speedMult;
if(xPos<0)
{
xPos=0;
xSpeed =-1.0*xSpeed;
}
if(yPos<0)
{
yPos=0;
ySpeed =-1.0*ySpeed;
}
if(xPos>width)
{
xPos=width;
xSpeed =-1.0*xSpeed;
}
if(yPos>height)
{
yPos=height;
ySpeed =-1.0*ySpeed;
}
}
}
核心知识就是 getValue();
可以自定义两点的距离,线条淡化的程度,粒子移动的速度,线条的宽度,清理屏幕。
绘制椭圆
void setup()
{
size(640,480);
}
void draw()
{
background(0,0,0);
float piAmt =map(mouseX,0,width,0,PI*2.0);
println(piAmt);
arc(width/2,height/2,250,250,0,piAmt);
}
arc(a,b,c,d,start,stop);在屏幕上绘制圆弧。a是圆弧的原点坐标x,b是原点坐标Y,start是绘制起点,stop是绘制终点。
arc(a,b,c,d,start,stop,mode);mode代表不同的模式,有PIE,OPEN,CHORD;
OPEN模式
PIE模式
CHORD模式
noise随机数
void setup()
{
size(400,400);
}
void draw()
{
background(0);
for(int y =0;y<height;y++)
{
for(int x=0;x<width;x++)
{
stroke(random(255));
point(x,y);
}
}
}
遍历屏幕上所有的像素点并改变颜色 在stroke()中加入随机值产生雪花屏效果。
void setup()
{
size(400,400);
}
void draw()
{
background(0);
for(int y =0;y<height;y++)
{
for(int x=0;x<width;x++)
{
float noiseNum =noise(x,y)*255.0;
stroke(noiseNum);
point(x,y);
}
}
}
在使用noise函数后会出现一定的重复性。
noise()是一个随机序列生成器,与标准random()函数相比,该序列生成的数字序列更自然,谐波连续。
noise(x);
noise(x,y);
noise(x,y,z);
x:噪声空间的x坐标
y:噪声空间的y坐标
z:噪声空间的z坐标
float time =0;
void setup()
{
size(400,400);
}
void draw()
{
background(0);
for(int y =0;y<height;y+=10)
{
for(int x=0;x<width;x+=10)
{
float noiseX =(float)x*0.01;
float noiseY =(float)y*0.01;
float angle =noise(noiseX,noiseY,time) * TWO_PI;
stroke(255);
pushMatrix();
translate(x,y);
rotate(angle);
line(0,0,5,5);
popMatrix();
point(x,y);
}
}
time+=0.01;
}
让线条动起来。
利用sin()函数绘图
int numberWaves =6;
Wave [] waves;
void setup()
{
size(800,600);
waves =new Wave[numberWaves];
for(int i =0;i<waves.length;i++)
{
waves[i] =new Wave();
}
}
void draw()
{
background(255);
for(int i =0;i<waves.length;i++)
{
waves[i].draw();
}
}
class Wave
{
float offset;
float offsetSpeed;
float waveHeight;
float totalLength;
float circleSize;
Wave()
{
offset =random(0,1);
offsetSpeed =random(0.001,0.01);
waveHeight =random(50,300);
totalLength =TWO_PI*random(1,10);
circleSize=random(2,15);
}
void draw()
{
fill(0);
for(float a= 0;a<totalLength;a+=0.1)
{
float angle =a+offset;
if(angle>totalLength)
angle =angle-totalLength;
float x =map(angle,0,totalLength,0,width);
float y =height/2+sin(angle)*waveHeight;
ellipse(x,y,circleSize,circleSize);
}
offset+=offsetSpeed;
if(offset>TWO_PI)
{
offset =0.0;
}
}
}
map(value,start1,stop1,start2,stop2);
value:要转换的传入值;
start1:该值当前范围的下限;
stop1:该值当前范围的上限;
start2:值目标范围的下限;
stop2:值目标范围的上限;