processing_processingobjectmodel - CSDN
• 这是我用processing写出的扩散效果 package Exercise; import processing.core.PApplet; import processing.core.PGraphics; import processing.core.PImage; /** * @author Administrator * */ public class ...
环形扩散
这是我用processing写出的扩散效果

package Exercise;
import processing.core.PApplet;
import processing.core.PGraphics;
import processing.core.PImage;

/**
*
*/
public class Animation {
//声明全局变量
PApplet zoomApplet;

//// 扩散的圆圈
PImage photo;
int animateWidth;
int animateHeigth;
int centerX;
int centerY;

private int progressive = 1;
private int circleAlpha = 255;

//构造函数
public Animation(PApplet zoomApplet,int animateWidth,int animateHeigth,int centerX,int centerY) {
this.zoomApplet = zoomApplet;
this.animateWidth = animateWidth;
this.animateHeigth = animateHeigth;
this.centerX = centerX;
this.centerY = centerY;
}

//镭射线效果

}

zoomGraphics.noFill();
//zoomGraphics.image(photo, 0, 0);
float pointX;
float pointY;
zoomGraphics.strokeWeight(10);
for(int i=0;i<180;i++)
{
int angle = i*2;
zoomGraphics.stroke(zoomGraphics.color(angle,180,60));
float originX = centerX + PApplet.cos((float) (angle*Math.PI/180))*radius;
float originY = centerY + PApplet.sin((float) (angle*Math.PI/180))*radius;
pointX = centerX + PApplet.cos((float) (angle*Math.PI/180))*(radius - 20);
pointY = centerY + PApplet.sin((float) (angle*Math.PI/180))*(radius - 20);
zoomGraphics.line(originX, originY, pointX, pointY);
float pointX1 = centerX + PApplet.cos((float) (angle*Math.PI/180))*(secondRadius-20);
float pointY1 = centerY + PApplet.sin((float) (angle*Math.PI/180))*(secondRadius-20);
float pointX2 = centerX + PApplet.cos((float) (angle*Math.PI/180))*secondRadius;
float pointY2 = centerY + PApplet.sin((float) (angle*Math.PI/180))*secondRadius;
zoomGraphics.line(pointX1, pointY1, pointX2, pointY2);
}
}
}
}
}

}

}

}

火 焰
这是我用processing写出的火焰效果

河 流
这是我用processing写出的类似于河流的效果

海 域
这是我用processing写出的一片海域的效果

以上三个是做出来的效果，下面上processing代码
火焰
package Exercise;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;

import processing.core.PApplet;
import processing.core.PImage;
import processing.core.PVector;

public class FireApplet extends PApplet{
/**
*
*/
private static final long serialVersionUID = 1L;

//初始化自定义粒子系统类变量
ParticleSystem particleSystem;

//动画的初始化方法
public void setup()
{
size(800,800);
particleSystem = new ParticleSystem(0, new PVector(width/2,500), image);
}
//动画的绘画方法
public void draw()
{
background(0);
float dx = map((float)mouseX, 0, (float)width, (float)-0.2, (float)0.2);
PVector wind = new PVector(dx,0);
//particleSystem.applyForce(wind);
particleSystem.run();
for (int i = 0; i < 2; i++) {
}
}

// TODO 创建Particle类有助于降低复杂度
class Particle {
PVector loc;
PVector vel;
PVector acc;
float lifespan;
PImage image;
Particle(PVector pVector,PImage img) {
acc = new PVector(0,0);
float vx = (float) (randomGaussian()*0.3);
float vy = (float) (randomGaussian()*0.3 -1.0);
vel = new PVector(vx,vy);
loc = CloneSeries.clone(pVector);
lifespan = 100;
image = img;

}
void run()
{
update();
render();
}
void applyForce(PVector fPVector)
{
}
void update()
{
lifespan -= 2.5;
acc.mult(0);
}
void render()
{
imageMode(CENTER);
tint(255,lifespan);
image(image,loc.x,loc.y);
}
{
if (lifespan<=0) {
return true;
}
else
{
return false;
}
}
}

// TODO 创建Particle系统类
class ParticleSystem
{
ArrayList<Particle>particles;
PVector origin;
PImage image;

ParticleSystem(int num,PVector v,PImage img) {
particles = new ArrayList<Particle>();
origin = CloneSeries.clone(v);
image = img;
for(int i=0;i<num;i++)
{
}
}
void run()
{
for(int i=particles.size()-1;i>=0;i--)
{
Particle particle = particles.get(i);
particle.run();
particles.remove(i);
}
}
}
void applyForce(PVector dir)
{
for(Particle p:particles)
{
p.applyForce(dir);
}
}
{
}
}

static class CloneSeries {
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T obj){
T cloneObj = null;
try {
//写入字节流
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream obs = new ObjectOutputStream(out);
obs.writeObject(obj);
obs.close();
//分配内存，写入原始对象，生成新对象
ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
ObjectInputStream ois = new ObjectInputStream(ios);
//返回生成的新对象
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return cloneObj;
}
}
}


河流
package Exercise;

import java.awt.Container;

import processing.core.PApplet;
import processing.core.PGraphics;
import processing.core.PImage;

public class RiverApplet extends PApplet{

/**
*
*/
private static final long serialVersionUID = 1L;
PGraphics riverPhics;
PApplet riverApplet;
float yoff = (float) 0.0;        // 2nd dimension of perlin noise
int  [] xRows;
int  [] yRows1;
int  [] yRows2;
PImage[] plan3DImage;

public void setup() {
size(1000,1000);
}

public void draw() {

//
clear();
background(color(16,120,180));
fill(color(60,140,255));
// We are going to draw a polygon out of the wave points
beginShape();
float xoff = 0;   // Option #1: 2D Noise
//float xoff = yoff; // Option #2: 1D Noise
// Iterate over horizontal pixels
for (float x = 0; x <= width; x += 5) {
// Calculate a y value according to noise, map to
float y = map(noise(xoff, yoff), 0, 1, 250,300); // Option #1: 2D Noise
//float y = map(noise(xoff), 0, 1, 200,300); // Option #2: 1D Noise
// Set the vertex
vertex(x, y);
// Increment x dimension for noise
xoff += 0.05;
}
for (float x2 = width; x2 >=0; x2 -= 5) {
// Calculate a y value according to noise, map to
float y2 = map(noise(xoff, yoff), 0, 1, 450,500); // Option #1: 2D Noise
//float y = map(noise(xoff), 0, 1, 200,300); // Option #2: 1D Noise
// Set the vertex
vertex(x2, y2);
// Increment x dimension for noise
xoff += 0.05;
}
// increment y dimension for noise
yoff += 0.01;
endShape(CLOSE);

}


//以上这个是使用noise（）方法绘制出来的效果，这种效果很逼真，但是无法根据实际的河流坐标进行修改，所以我使用了下面的这个方法，绘制特定路线的河流，并添加河流的动画效果
package Exercise;

import java.awt.Container;

import processing.core.PApplet;
import processing.core.PGraphics;
import processing.core.PImage;

public class RiverApplet extends PApplet{

/**
*
*/
private static final long serialVersionUID = 1L;
PGraphics riverPhics;
PApplet riverApplet;
float yoff = (float) 0.0;        // 2nd dimension of perlin noise
int  [] xRows;
int  [] yRows1;
int  [] yRows2;
PImage[] plan3DImage;

public void setup() {
size(1000,1000);

setupRiverLines();
}

public void draw() {

riverPhics.beginDraw();
riverPhics.background(102);
riverPhics.stroke(255);
drawRiverLines();
riverPhics.endDraw();
plan3DImage[0] = riverPhics.get();
image(riverPhics, 100, 100);
frameRate(5);
//

public void setupRiverLines()
{
plan3DImage = new PImage[1];
//background(255);
riverPhics = createGraphics(800, 800);

riverPhics.background(255);
xRows = new int [21];
yRows1 = new int [21];
yRows2 = new int [21];
}
public void drawRiverLines() {

riverPhics.stroke(color(0));
riverPhics.strokeWeight(8);
//riverPhics.fill(75,121,199);
for(int i=0;i<=20;i++)
{
xRows[i] = 40*i;
yRows1[i] = (int) (random(100, 150) + 60);
yRows2[i] = (int) (random(200, 250) + 160);
}

riverPhics.beginShape();

for(int j=0;j<xRows.length;j++)
{
riverPhics.curveVertex(xRows[j], yRows1[j]);
}
for(int k=xRows.length;k>0;k--)
{
riverPhics.curveVertex(xRows[k-1], yRows2[k-1]);
}
riverPhics.endShape();

}

}


海域
package Exercise;

import processing.core.PApplet;
import processing.core.PShape;

public class SeaApplet extends PApplet {
/**
*
*/
private static final long serialVersionUID = 1L;
int screenWidth = 800;
int screenHeigth = 800;
float increment = (float) 0.01;
int directX = -1;// X轴移动方向1\-1
int directY = 1;// Y轴移动方向1\-1
float moveMent = (float) 0.05;// 代表海面移动速度0.1--0.01之间
float xoff = 0;
float yoff = 0;
int  [] xRows;
int  [] yRows;
int loopNum;

// 启动程序入口
public void setup() {

size(screenWidth, screenHeigth,P2D);
background(15, 101, 180);

drawShapeLine();

fill(color(60, 140, 255));
stroke(0);
}

// 循环绘画方法
public void draw() {

// 循环海域，绘制noise即浪花
xoff = yoff = increment;
for (int x = 0; x <= 650; x++) {
yoff = increment;
for (int y = 0; y < height; y++) {
float rcolor = map(noise(xoff, yoff), 0, 1, 10, 60);
float gcolor = map(noise(xoff, yoff), 0, 1, 80, 120);
float bcolor = map(noise(xoff, yoff), 0, 1, 160, 255);
// System.out.println("R:"+rcolor+"G:"+gcolor+"B:"+bcolor);
if (x<=100) {
set(x, y, color(rcolor, gcolor, bcolor));
}
else if (x>100&&x<=200) {
caculateMethod(100, 800, 250, 550);
boolean isIn = DownAnalysePoint(x, y);
if (isIn) {
set(x, y, color(rcolor, gcolor, bcolor));
}
}
else if (x>200&&x<=250&&y>550) {
caculateMethod(100, 800, 250, 550);
boolean isIn = DownAnalysePoint(x, y);
if (isIn) {
set(x, y, color(rcolor, gcolor, bcolor));
}
}
else if (x>200&&x<=250&&y<=550) {
caculateMethod(200, 0, 500, 80);
boolean isIn = UpAnalysePoint(x, y);
if (isIn) {
set(x, y, color(rcolor, gcolor, bcolor));
}
}
else if (x>250&&x<=350&&y<=550) {
caculateMethod(200, 0, 500, 80);
boolean isIn = UpAnalysePoint(x, y);
if (isIn) {
set(x, y, color(rcolor, gcolor, bcolor));
}
}
else if (x>250&&x<=350&&y>550) {
caculateMethod(350, 750, 250, 550);
boolean isIn = DownAnalysePoint(x, y);
if (isIn) {
set(x, y, color(rcolor, gcolor, bcolor));
}
}
else if (x>350&&x<=500&&y<=80) {
caculateMethod(200, 0, 500, 80);
boolean isIn = UpAnalysePoint(x, y);
if (isIn) {
set(x, y, color(rcolor, gcolor, bcolor));
}
}
else if (x>350&&x<=500&&y>80) {
caculateMethod(350, 750, 600, 500);
boolean isIn = DownAnalysePoint(x, y);
if (isIn) {
set(x, y, color(rcolor, gcolor, bcolor));
}
}
else if (x>500&&x<=550&&y<=350) {
caculateMethod(500, 80, 600, 50);
boolean isIn = UpAnalysePoint(x, y);
if (isIn) {
set(x, y, color(rcolor, gcolor, bcolor));
}
}
else if (x>500&&x<=550&&y>350) {
caculateMethod(350, 750, 600, 500);
boolean isIn = DownAnalysePoint(x, y);
if (isIn) {
set(x, y, color(rcolor, gcolor, bcolor));
}
}
else if (x>550&&x<=600&&y<=80) {
caculateMethod(500, 80, 600, 50);
boolean isIn = UpAnalysePoint(x, y);
if (isIn) {
set(x, y, color(rcolor, gcolor, bcolor));
}
}
else if (x>550&&x<=600&&y<=350&&y>80) {
caculateMethod(550, 350, 650, 150);
boolean isIn = DownAnalysePoint(x, y);
if (isIn) {
set(x, y, color(rcolor, gcolor, bcolor));
}
}
else if (x>550&&x<=600&&y>350&&y<=500) {
caculateMethod(550, 350, 600, 500);
boolean isIn = UpAnalysePoint(x, y);
if (isIn) {
set(x, y, color(rcolor, gcolor, bcolor));
}
}
else if (x>550&&x<=600&&y>500) {
caculateMethod(350, 750, 600, 500);
boolean isIn = DownAnalysePoint(x, y);
if (isIn) {
set(x, y, color(rcolor, gcolor, bcolor));
}
}
else if (x>600&&x<=650&&y<=350&&y<=150) {
caculateMethod(600, 50, 650, 150);
boolean isIn = UpAnalysePoint(x, y);
if (isIn) {
set(x, y, color(rcolor, gcolor, bcolor));
}
}
else if (x>600&&x<=650&&y<=350&&y>150) {
caculateMethod(550, 350, 650, 150);
boolean isIn = DownAnalysePoint(x, y);
if (isIn) {
set(x, y, color(rcolor, gcolor, bcolor));
}
}

yoff += (0.01 * directY);
}
xoff += (0.01 * directX);
}
increment += moveMent;

// 海岸线拐点(0,0)(200,0)(500,80)(600,50)(650,150)(550,350)(650,500)(350,750)(250,550)(100,800)(0,800)
// 开始绘制海域
//		noFill();
//				beginShape();
//				vertex(width, 0);
//				vertex(200, 0);
//				vertex(500, 80);
//				vertex(600, 50);
//				vertex(650, 150);
//				vertex(550, 350);
//				vertex(600, 500);
//				vertex(350, 750);
//				vertex(250, 550);
//				vertex(100, 800);
//				vertex(width, height);
//				endShape(CORNER);
// 绘画帧数
frameRate(20);

}

public void drawShapeLine()
{
loopNum = 0;
//坐标数组
xRows = new int [11];
yRows = new int [11];
xRows[0] = width;
yRows[0] = 0;
xRows[1] = 200;
yRows[1] = 0;
xRows[2] = 500;
yRows[2] = 80;
xRows[3] = 600;
yRows[3] = 50;
xRows[4] = 650;
yRows[4] = 150;
xRows[5] = 550;
yRows[5] = 350;
xRows[6] = 600;
yRows[6] = 500;
xRows[7] = 350;
yRows[7] = 750;
xRows[8] = 250;
yRows[8] = 550;
xRows[9] = 100;
yRows[9] = height;
xRows[10] = width;
yRows[10] = height;
System.out.println("数组："+xRows+yRows);

noFill();
stroke(color(123,123,123));
beginShape();
curveVertex(xRows[loopNum], yRows[loopNum]);
for(int i=loopNum;i<=10;i++)
{
curveVertex(xRows[i], yRows[i]);
}
if (loopNum>0&&loopNum<11) {
for(int i=0;i<loopNum;i++)
{
curveVertex(xRows[i], yRows[i]);
}
curveVertex(xRows[loopNum], yRows[loopNum]);
}
else
{
curveVertex(xRows[10], yRows[10]);
}
loopNum++;
if (loopNum>10) {
loopNum=0;
}
endShape(CLOSE);
}
double [] result;
public double[] caculateMethod(int x1,int y1,int x2,int y2)
{
y1 = screenHeigth-y1;
y2 = screenHeigth-y2;
result = new double[2];
float k,a;
k=(float)(y2-y1)/(x2-x1);
a=y2-k*x2;
result[0]=k;
result[1]=a;
return result;
}
public boolean UpAnalysePoint(int x,int y)
{
float resultY = 0;
y = screenHeigth-y;
if (result!=null) {
float k=(float) result[0];
float a=(float) result[1];
resultY=  k*x + a;
}
if (resultY>=y) {
return true;
}
else
{
return false;
}

}

public boolean DownAnalysePoint(int x,int y)
{
float resultY = 0;
y = screenHeigth-y;
if (result!=null) {
float k=(float) result[0];
float a=(float) result[1];
resultY=  k*x + a;
}
if (resultY<=y) {
return true;
}
else
{
return false;
}

}

}


//这个方法的核心依然是noise（）。
以上就是项目中使用到的动画效果。


展开全文
• processing写的数据可视化的效果，具体分析的是企业网络数据，约十万行的数据。。采用的可视化效果是星空图。星空图有简单的交互功能。 自己参考文献写出来的小东西，没有用什么高深的算法，很简单理解。 做了一些...
• Processing——《下雪的季节》可视化流程 一、前言 灵感来源（也谈不上灵感吧）：正值冬季，下雪的季节，做做雪花飘落的“特效 ”也别有一番风味（虽然挺low的，哈哈哈）。更者，正好有一首歌，即名为《下雪的季 ...
Processing——《下雪的季节》可视化流程
一、前言
             灵感来源（也谈不上灵感吧）：正值冬季，下雪的季节，做做雪花飘落的“特效
”也别有一番风味（虽然挺low的，哈哈哈）。更者，正好有一首歌，即名为《下雪的季
节》，所以就又想做些音乐可视化的东西吧，也算锦上添花。


二、飘雪的实现
       有了有趣的想法就开始实现吧，先从比较容易的来写，雪花的绘制。
雪花如果一点点的画那就很难画了，所以这里用了分形的方法画——即递归。
废话不多说直接上代码，代码上有注释

import java.util.Iterator;

snowsystem snow;

void setup() //建画板
{
size(1280,1080);
snow =new snowsystem(0.3);  //雪花下落频率
}
void draw() //重复执行，绘制雪花及其下落过程（动态）
{
background(40);
stroke(240);
snow.run();
}

class Branch  //雪花6个主分叉的其中一个的绘制——分支类
{
ratio=ratio_;
rotation=rot;
}
void generate()//类方法 ——生成完整的一支雪花分枝
{
pushMatrix();
branch(len);//递归函数
popMatrix();
}
void branch(float len)//主递归函数
{
strokeWeight(len*0.15); //线粗细
strokeCap(ROUND);      //线端点平滑
line(0,0,0,-len);              //画线
translate(0,-len);            //移动

if(len>2) //递归终止条件
{
pushMatrix();
branch(len*ratio);
popMatrix();

pushMatrix();
branch(getStartLength(len,ratio));
popMatrix();

pushMatrix();
branch(getStartLength(len,ratio));
popMatrix();
}
}

float getStartLength(float length,float  ratio)//生成下次开始产生分叉的起点长度
{
float len=(1-ratio)*length;
return len;
}
}

class snowflake  //雪花类
{
PVector position ,velocity;
Branch[] branches=new Branch[6];

snowflake(PVector pos,PVector vel,float rot,float aVel,float r,float rat)//构造函数并赋值
{
position =pos;
velocity=vel;
rotation=rot;
aVelocity=aVel;
ratio=rat;

}

void update()
{
rotation+=aVelocity;  //角速度
}
void show()
{
pushMatrix();
translate(position.x,position.y);
for(Branch b:branches)
{b.generate();}
popMatrix();
}
}

class snowsystem   //雪花下落类
{
float speed ;
ArrayList<snowflake> snowflakes;

snowsystem (float speed_){
speed=speed_;
snowflakes=new ArrayList<snowflake>();
}

void  generate() //随机生成新雪花（多个）
{
PVector position =new PVector(random(0,width),0);
PVector velocity =new PVector(0,random(5,10));
float rotation =random(0,360);
float aVel=random(-2,5);
float ratio=0.618;
}

void  emit()  //控制雪的大小的函数 （speed一般小于1，否则会比较卡，看电脑配置吧）
{
if(speed >=1)
{
for(int i=0;i<speed;i++){ generate();}
}
else if(speed>0){if(random(1)<speed){generate();}}
}

void update()  //清除落到画布外的雪花
{
Iterator<snowflake> ite=snowflakes.iterator(); //迭代器，相当于c++中的队列，按顺序移除进入的雪花
while(ite.hasNext()){snowflake s=ite.next();s.update();s.show(); //在画布中显示下雪的情状
}
}
void run () //执行雪花下落
{ emit();update();}
}


音乐可视化
            雪花效果出来了 ，下面就是可视化的流程了
processing 提供了两个音频库，一个是sound库；一个是minim库。
这里我用的minim。
ok，直接上代码了就。（部分代码）（比较简单就不写注释了）

import ddf.minim.*;

Minim minim;
AudioPlayer player;
void setup(){
size(1280,626);
minim = new Minim(this);
frameRate(24);
}
void draw(){
background(0);
if(player.left.level()<=player.right.level()){
int r=int(random(255));
int g=int(random(255));
int b=int(random(255));
stroke(r,g,b);
}
translate(width /9, height / 5);
float bins=1024;//最大1024
for(int i=0;i<bins -1;i++) {
strokeWeight(2);
float r1 = 200 + 150 * player.left.get(i);
float r2 = 200 + 150 * player.left.get(i+1);
float R1 = 200 + 150 * player.right.get(i);
float R2 = 200 + 150 * player.right.get(i+1);
float rad1 = 2 * PI * (i / bins);
float rad2 = 2 * PI * ((i + 1) / bins);
float Rad1 = 2 * PI * (i / bins);
float Rad2 = 2 * PI * ((i + 1) / bins);
}
noFill();
arc(500, 200, 300*player.left.level()*5, 300*player.left.level()*5, -2*PIE, 2*PIE);
arc(500, 200, 300*player.right.level()*5, 300*player.right.level()*5, -2*PIE, 2*PIE);

translate(-width / 9, -height / 5);
if( player.isPlaying() )
{
text("Press any to pause playback.", 10, 20);
}
else
{
text("Press any key to start playback.", 10, 20
);
}
stroke(225);
snow.run();
}
void keyPressed() //键盘交互
{
if( player.isPlaying() ) {
player.pause();
}
else if ( player.position() == player.length() ) {
player.rewind();
player.play();
} else
{
player.play();
}
}


              这样一个demo就出来了，难免有些单调，后面优化一下。

三、完成了哦！

     加了背景，简短的几句代码，就不写了

四、总结
       只是做了些比较简单粗糙的可视化的内容，但是色彩以及波纹的变换还是会带来一定的
视觉冲击的。同时雪花的飘落配上bgm也是非常有意境的。
而往往更多被用到的手绘，想要达到这种效果简直难到头秃。所以对于做些酷酷的东西
还是果断选择码绘吧。

五、参考链接
openprocessing的大佬示例
b站 ： AV11187821(分形雪花教学)。


展开全文
• /* @pjs preload="data/mummo.jpg"; */ float x; PImage photo; void setup() { size(940, 705); x = width; photo = loadImage("AddImage.jpg"... image(photo, x, 0)...
/* @pjs preload="data/mummo.jpg"; */

float x;
PImage photo;

void setup() {
size(940, 705);
x = width;
}
void draw() {
background(0);

image(photo, x, 0);

if(x > 0) {
x = x - 1;
}
}



通过更新  图片的x 轴的坐标不断刷新图片的显示位置，使图片看上去从右向左移动出来

image(img, a, b)
image(img, a, b, c, d)

IMG
PImage：要显示的图像
a
float：默认情况下图像的x坐标
b
float：默认情况下图像的y坐标
C
float：width默认显示图像
d
float：height默认显示图像

效果图如下：


展开全文
• 上课作业做的个processing的个小小打飞机游戏
• processing代码学习，是一种具有革命前瞻性的新兴计算机语言，它的概念是在电子艺术的环境下介绍程序语言，并将电子艺术的概念介绍给程序设计师。它是 Java 语言的延伸，并支持许多现有的 Java 语言架构，不过在语法...
• Processing 在 2001 年诞生于麻省理工学院（MIT）的媒体实验室，主创者为 Ben Fry 和 Casey Reas，项目发起的初衷，本是为了满足他们自身的教学和学习需要。后来，当Casey在意大利的伊夫雷亚交互设计学院...
Processing 在 2001 年诞生于麻省理工学院（MIT）的媒体实验室，主创者为 Ben Fry 和 Casey Reas，项目发起的初衷，本是为了满足他们自身的教学和学习需要。后来，当Casey在意大利的伊夫雷亚交互设计学院（Interaction Design Institute Ivrea）进行教学的时候，基于Processing，衍生出了Wiring和Arduino项目。随着时间的推移，又诞生了多个语言的版本，比如基于JavaScript的Processing.js，还有基于Python、Ruby、ActionScript以及Scala等版本。而当前的Processing，成立了相应的基金会，由基金会负责软件的开发和维护工作。

Processing项目是Java开发的，所以Processing天生就具有跨平台的特点，同时支持Linux、Windows以及Mac OSX三大平台，并且支持将图像导出成各种格式。对于动态应用程序，甚至可以将 Processing 应用程序作为 Java™ applet 导出以用在 Web 环境内。当然，为了降低设计师的学习门槛，用Processing进行图形设计的编程语言并不是Java，而是重新开发了一门类C的编程语言，这也让非计算机科班出身的设计师很容易上手。这里要多提一句，Processing支持OpenGL和WebGL，不但可以渲染2D图形，还可以渲染3D图形。

在过去的2015年，随着移动设备的普及，以及各大浏览器厂商对HTML5的支持日渐成熟，Processing也迎来了一次重大的升级。不但对开发工具做了优化和完善，也开始逐步支持Android应用的开发。Web方面，基于HTML5，重新开发了JavaScript版本的Processing，并且单独为其提供了Web开发工具，同时这也让Processing在网页上开发应用变的更加简单便捷。这里顺便提及一点的是，Processing可不只是能够渲染漂亮的图形，还支持与其他软件的通信，结合之前提到的Arduino项目，甚至可以和外部硬件进行交互！

Processing免费供设计爱好者们下载使用，官网：https://processing.org

1、Processing 环境：

这应该会弹出 Processing Development Environment（PDE 或 Processing IDE），如图 1 所示。占此窗口较大的部分是文本编辑器。如果输入图中所示的两行代码，然后单击 Run（左上角的三角形），出现一个窗口，显示您所输入的简单程序（或 Processing 术语所指的 sketch）的结果。单击 Stop（左上角的方框）退出程序，窗口消失。

2、Processing 语言Processing 是用 Java 编程语言写的，并且 Java 语言也是在语言树中最接近 Processing 的。所以，如果您熟悉 C 或 Java 语言，Processing 将很容易学。并且在程序如何构造方面，也作了一些简化。Processing 并不包括 Java 语言的一些较为高级的特性，但这些特性中的很多特性均已集成到了 Processing， 所以您无需了解它们。

之所以选择 Java 语言是因为 Processing 应用程序被翻译成 Java 代码执行。选择 Java 范型简化了这种翻译并让开发和执行可视化程序变得十分简单和直观。

3、图形环境

在 Processing 内进行开发涉及到的是 PDE 和显示窗口。2-D 图形的坐标系如图 2 所示。size 关键字以像素为单位定义了显示窗口的大小并且通常都是 Processing 应用程序内的首要步骤。

如图 2 所示，size 关键字指定显示窗口的 X 和 Y 坐标。line 关键字则会在两个像素点之间绘制一条线（以 x1、y1 to x2、y2 的格式）。请注意，超出屏幕边界（size 定义的边界外）画线并非不允许，只是被忽略了而已。

本文无意对此做深入探讨，但 size 接受可选的第三个参数 mode。 mode 用来定义要使用的呈现引擎并支持 PDF（直接呈现为 Adobe® PDF 文档）、OPENGL （利用一个可用的 Open-GL 图形适配器）、P3D（为了迅速的 3-D 呈现）等。默认的是 JAVA2D，它最适合于高质量的 2-D 成像。

现在，我们来看一些基本的图形原语，然后再深入探讨几个示例应用程序。

4、图形原语

Processing 包含了大量各种各样的几何形状以及这些形状的控件。本节会简介一些基本的图形原语。

1）背景和颜色
background 功能被用来设置显示窗口的颜色。此函数可以使用各种不同的参数（来定义一个灰度值或 Red-Green-Blue [RGB] 颜色）。

size(100, 100);
background( 0, 128, 0 );

2）绘制像素点
可以使用 set 函数绘制单个像素点。此函数接受显示窗口内的 x,y 坐标以及作为颜色的第三个参数。Processing 也有一个类型，称为 color，通过它，可以定义用于某个操作的颜色。在本例中，我们创建了一个颜色实例并用它来设置显示窗口内的某个像素点。

size(100, 100);
for (int x = 0 ; x < 100 ; x++) {
for (int y = 0 ; y < 100 ; y++) {
color c = color( x*2, y*2, 128 );
set(x, y, c);
}
}

可以使用 get 操作来读取显示中的一个给定像素点的颜色。虽然 set 很简单，但它不是操做显示的最快方式。要想快速访问，可以使用 pixels 数组（与 loadPixels 和 updatePixels 函数一致）。

3）绘制形状

在 Processing 内使用单个函数绘制形状十分简单。要设置在绘制形状时使用何种颜色，可以利用 stroke 函数。此函数可接受一个单独的灰度参数或三个 RGB 参数。此外，还可以用 fill 命令定义这个形状的填充色。

下面代码显示了如何绘制线、矩形、圆（使用椭圆）及椭圆。line 函数接受四个参数，代表的是要在其间绘制线条的点。rect 函数可绘制一个矩形，并且前两个点定义位置，而后面两个点则分别定义宽度和高度。ellipse 函数也接受四个参数，分别定义位置和宽/高度。当宽和高相等时，就是一个圆形。还可以使用 ellipseMode 函数定制椭圆，它指定 x,y 位置是否代表了椭圆的角（CORNER）或中心（CENTER）。

size(100, 100);
stroke(0, 128, 0);
line(10, 10, 90, 90);

fill(20, 50, 150);
rect(30, 30, 60, 40);

fill(190, 0, 30);
ellipse(30, 70, 20, 20);

fill(0, 150, 90);
ellipse(70, 30, 30, 20);

4）绘制四边形

在 Processing 内使用 quad 可以很容易地绘制有四个边的多边形。四边形接受八个参数，代表的是这个四边形的四个顶点。清单 4 内的示例创建了 10 个随机的四边形（其中这些点必须是顺时针或逆时针顺序。此代码还会为每个四边形创建一个随机的灰度。

size(100, 100);

for (int i = 0 ; i < 10 ; i++) {

int x1 = (int)random(50);
int y1 = (int)random(50);
int x2 = (int)random(50) + 50;
int y2 = (int)random(50);
int x3 = (int)random(50) + 50;
int y3 = (int)random(50) + 50;
int x4 = (int)random(50);
int y4 = (int)random(50) + 50;

fill( color((int)random(255) ) );

quad( x1, y1, x2, y2, x3, y3, x4, y4 );

}

上面几个例子的结果

5、Processing 应用程序的结构

至此，通过几个简单的脚本，您已经对 Processing 语言有了大致的了解，但这些脚本是一些非结构化的代码，只提供了应用程序的一些简单元素。Processing 应用程序是有一定结构的，这一点在开发能够持续运行且随时更改显示窗口的图形应用程序（比如动画）时非常重要。在这种情况下，就凸显了 setup 和 draw 这两个函数的重要性。

setup 函数用于初始化，由 Processing 运行时执行一次。通常，setup 函数包含 size 函数（用于定义窗口的边界）以及在操作期间要使用的变量的初始化。Processing 运行时会不断执行 draw 函数。每次 draw 函数结束后，就会在显示窗口绘制一个新的画面，并且 draw 函数也会被再次调用。默认的绘制速度是每秒 60 个画面，但是您也可以通过调用 frameRate 函数来更改这个速度。

此外，还可以使用 noLoop 和 draw 来控制在何时绘制画面。noLoop 函数会导致绘制停止，而使用 loop 函数则可以重新开始绘制。通过调用 redraw 可以控制 draw 在何时调用。

下面我们做一个简单的模拟仿真，示例1：

实现森林火灾模型的 2-D 元胞自动机实现。这个模型来自 Chopard 和 Dro 的 “物理系统的元胞自动机建模”，它提供了一个简单系统，展示了树的生长以及由雷击导致的大火的蔓延。这个模拟包含了一组简单规则，定义如下：

在一个空场地（灰色），一棵树以 pGrowth 的机率成长。
如果其相邻树中有至少有一棵树正在燃烧，那么这颗树也会成为一棵燃烧树（红色）。
一棵燃烧树（红色）成为一个空场地（灰色）。
如果周围没有任何燃烧树，那么这个树成为燃烧树的可能性为 pBurn。比如由雷击导致的燃烧，就是其中的一种可能。
这些规则的代码可以在 update 函数（下面代码）内找到，它迭代 2-D 空间以决定根据已定义的规则，状态如何转换。请注意这个 2-D 空间实际上是 3-D 的，因为保存了此空间的两个副本 — 一个针对的是当前迭代，一个针对的是上一个迭代。这么做是为了避免更改对空间的破坏。此空间然后会成为一个显示空间（被显示的东西） 和一个计算空间（规则的应用）。这些空间按每次生成对调。

从很大程度上讲，这个应用程序使用了极少的 Processing 图形关键字。为空间定义的颜色只有几个：stroke 用来更改颜色，point 用于绘制像素点。使用 Processing 模型，draw 函数调用 update 以应用规则；返回后，draw 将这个更新了的空间发到显示窗口。

int[][][] pix = new int[2][400][400];
int toDraw = 0;

int tree = 0;
int burningTree = 1;
int emptySite = 2;

int x_limit = 400;
int y_limit = 400;

color brown = color(80, 50, 10); // brown
color red   = color(255, 0, 0); // red;
color green = color(0, 255, 0); // green

float pGrowth = 0.01;
float pBurn = 0.00006;

boolean prob( float p )
{
if (random(0, 1) < p) return true;
else return false;
}

void setup()
{
size(400, 400);
frameRate(60);

/* Initialize to all empty sites */
for (int x = 0 ; x < x_limit ; x++) {
for (int y = 0 ; y < y_limit ; y++) {
pix[toDraw][x][y] = emptySite;
}
}

}

void draw()
{
update();

for (int x = 0 ; x < x_limit ; x++) {
for (int y = 0 ; y < y_limit ; y++) {

if        (pix[toDraw][x][y] == tree) {
stroke( green );
} else if (pix[toDraw][x][y] == burningTree) {
stroke( red );
} else stroke( brown );

point( x, y );

}
}

toDraw = (toDraw == 0) ? 1 : 0;
}

void update()
{
int x, y, dx, dy, cell, chg, burningTreeCount;
int toCompute = (toDraw == 0) ? 1 : 0;

for (x = 1 ; x < x_limit-1 ; x++) {
for (y = 1 ; y < y_limit-1 ; y++) {

cell = pix[toDraw][x][y];

// Survey area for burning trees
burningTreeCount = 0;
for (dx = -1 ; dx < 2 ; dx++) {
for (dy = -1 ; dy < 2 ; dy++) {
if ((dx == 0) && (dy == 0)) continue;
else if (pix[toDraw][x+dx][y+dy] == burningTree) burningTreeCount++;
}
}

// Determine next state
if      (cell == burningTree) chg = emptySite;
else if ((cell == emptySite) && (prob(pGrowth))) chg = tree;
else if ((cell == tree) && (prob(pBurn))) chg = burningTree;
else if ((cell == tree) && (burningTreeCount > 0)) chg = burningTree;
else chg = cell;
pix[toCompute][x][y] = chg;
}
}
}

运行结果

示例2：

易染/感染/免疫模型模拟的是疾病在医院内的蔓延。与森林火灾模型类似，SIR 也是通过一套简单规则实现的，只不过添加了一些复杂性和有趣的行为。 在这个模型内，有一个由病人占据的病床组成的网格。在 time 0，所有病人都是某一种新疾病的易染人群，这意味着这些病人从未患过这种疾病，因此才有可能被感染。如果在某个病人的东/南/西/北的四个邻居中有一个患了这种疾病，那么该病人受感染的可能性为 tau。一个受感染的病人的患病时间为 K 天，在此期间病人有感染其他病人的可能性。在 K 天后，该病人康复并有了对这种疾病的免疫力。

正如之前的例子所示，setup 函数先初始化这个医院以及所有易染病人，只有最中心的这个病人是已经患病的。在该实现内，0 是易染病人，1-K 是感染病人，-1 是免疫病人。draw 函数将这种几何分布发到显示窗口，update 实施这些 SIR 规则。与之前一样，可以用一个 3D 数组保存当前的这些几何分布。如下代码。

int[][][] beds = new int[2][200][200];
int toDraw = 0;

int x_limit = 200;
int y_limit = 200;

color brown = color(80, 50, 10); // brown
color red = color(255, 0, 0); // red;
color green = color(0, 255, 0); // green

int susceptible = 0;
int recovered = -1;

float tau = 0.2;
int k = 4;

boolean prob( float p )
{
if (random(0, 1) < p) return true;
else return false;
}

void setup()
{
size(200, 200);
frameRate(50);

for (int x = 0 ; x < x_limit ; x++) {
for (int y = 0 ; y < y_limit ; y++) {
beds[toDraw][x][y] = susceptible;
}
}
beds[toDraw][100][100] = 1;
}

void draw()
{
update();

for (int x = 0 ; x < x_limit ; x++) {
for (int y = 0 ; y < y_limit ; y++) {

if (beds[toDraw][x][y] == recovered) stroke( brown );
else if (beds[toDraw][x][y] == susceptible) stroke( green );
else if (beds[toDraw][x][y] < k) stroke( red );

point( x, y );

}
}

toDraw = (toDraw == 0) ? 1 : 0;
}

boolean sick( int patient )
{
if ((patient > 0) && (patient < k)) return true;
return false;
}

void update()
{
int x, y, cell;
int toCompute = (toDraw == 0) ? 1 : 0;

for (x = 1 ; x < x_limit-1 ; x++) {
for (y = 1 ; y < y_limit-1 ; y++) {

cell = beds[toDraw][x][y];

if (cell == k) cell = recovered;
else if (sick(cell)) cell++;
else if (cell == susceptible) {
if (sick(beds[toDraw][x][y-1]) || sick(beds[toDraw][x][y+1]) ||
sick(beds[toDraw][x-1][y]) || sick(beds[toDraw][x+1][y])) {
if (prob(tau)) cell = 1;
}
}

beds[toCompute][x][y] = cell;

}
}
}

Processing 内 SIR 模型的输出如图 7 所示。请注意这里这些绿色的像素点代表的是易染病人，红色的代表的是感染病人，灰色代表的是免疫病人。由于病症会持续 4 天，且相邻病人患病的可能性为 20 %，因此这个病症会随机地在整个医院传播，感染很多病人，但也有数群未被感染的病人。

5、使用文本
Processing 不仅支持显示窗口内的文本，还支持控制台形式的用于调试的文本。要在显示窗口内使用文本，需要一种字体。所以，第一步是创建一种字体（使用 PDE 的 Tools 选项）。选择了要创建的字体后，字体文件（VLW）就会显示在项目的 ./data 子目录内。之后，就可以使用 loadFont 函数加载这个文件，然后再使用 textFont 将它定义为默认。这两个步骤在 图 5 的 setup 函数内有所显示。还请注意我们已经将画面速度减慢为每秒 1 个画面 （因为这也是更新自然发生的频率）。

draw 函数展示了您在之前没有见过的其他一些函数。首先是时间函数，它返回的是时钟的小时、分和秒。请注意有一些传统的函数可以返回年、月和日。存储了时间数据后，就可以使用 nf 函数创建一个字符串，它可以将数字转变为字符串。为了将向时钟添加一些花样，可以使用 background 和 fill 函数处理背景和时钟的颜色。背景的颜色范围是从 255（白）到 137（淡灰）。fill 函数可用于给文本上色，范围是从 100 （淡灰）到 218（接近于黑色）。颜色设好后，text 函数就会向将时间字符串发送到显示窗口已定义的坐标位置。也可以使用 println 函数将字符串发到控制台，如下。


展开全文
• Processing是一个为开发面向图形的应用（visually orientedapplication）而生的简单易用的编程语言和编程环境。本文将简洁地向你描述Processing的下载、配置、使用方法和编程思路，希望本文能给你打开一扇通向自由...
• 机缘巧合下，接触到了processing，用来设计一个小游戏。嗯~，processing是个什么鬼，好吧，原谅各位程序员，程序媛啦！processing一般都是给设计人员用的。什么是processing Processing是一种计算机语言，以java...
• 我的Processing 打不了中文，只能用英文注释了，很简单的代码，有不明白的留评论 开始写之前，我要吐槽一下processing，同一个项目新建一个类，只能点这个三角形新建一个标签，或者是快捷键 ctrl+shift+n，丫的，让...
• 这周开始接触processing，首先下载就很痛苦,莫名地github就很难下。最后同学发来环境，竟然不用安装，体量也小。（面向设计师的东西果然都将设置对用户透明了） 然后开始临摹，开始很懵，除了在OPenGL做过那么几次...
• 这是本人第一次写博客，是写给自己看的吧，标志着我下定决心开始走程序媛这条路了。 而且这也是我第一次用Processing写小游戏，算是纪念了。
• processing3.4 window64位版本 Processing是一种具有革命前瞻性的新兴计算机语言，它的概念是在电子艺术的环境下介绍程序语言，并将电子艺术的概念介绍给程序设计师。它是 Java 语言的延伸，并支持许多现有的 Java ...
• HTTP Status 500 - Request processing failed; nested exception is org.springframework.jdbc.BadSqlGrammarException:type Exception reportmessage Request processing failed; nested exception is org.springf
• 新学了一个后期插件，靠着翻译...Postprocessing是一个unity2018版本的集成后期插件，有了这个插件，之后用unity开发时，后期调整颜色、光晕等会很方便。 新建一个postprocessing profile（配置文件）。    ...
• 由于我们在示波器中必须用到多线程，所以我们在实现示波器的动态获取数据功能之前，中间插一篇有关processing多线程的探索内容。 虽然，表面上processing和arduino的封装差不多，一开始都是一个setup，但我们知道要...
• 互动媒体技术——Processing创意绘画系统 总体设计思路 工具：Processing Processing是一个为开发面向图形的应用（visually oriented application）而生的简单易用的编程语言和编程环境。Processing的创造者将它....
• Processing 允许使用面向对象编程（OOP）技术来使 Processing 应用程序更易于开发和维护。与其他面向对象的语言一样，Processing 使用 Class 的概念来定义对象模板。 我们先来看一个例子：假设平坦的马路上跑着一...
• 基于processing的动画交互基本介绍总览结果分部设计及源代码1、 添加字体2、球随鼠标3、两个对象之间的引力4、小型粒子系统心得想法 基本介绍 大致看了《代码本色》这本书之后，在原有的编程经验的基础上，对于在...