sketch_dec06c_2010 是我个人已经在openProcessing 社区里开源的Processing 互动作品。这是个人第一个开始使用PVector 类来控制粒子轨迹的小程序。大家可以试着把GUI 里的ghost 数量提高,效果会更华丽。
import processing.opengl.*;
import controlP5.*;
Particle [] dots = new Particle[100];
ControlP5 controlP5;
Line lines;
int ghostV,thresholdV,thicknessV;
float velocityV;
Slider ghost,threshold,velocity,thickness;
void setup(){
size(600,576);
frameRate(30);
background(255);
controlP5 = new ControlP5(this);
ghost = controlP5.addSlider("ghost",10,255,100,30,485,100,14);
threshold = controlP5.addSlider("threshold",5,60,30,30,504,100,14);
velocity = controlP5.addSlider("velocity",-1,1,1,30,523,100,14);
thickness = controlP5.addSlider("thickness",0,10,2,30,542,100,14);
customizeSlider(ghost);
customizeSlider(threshold);
customizeSlider(velocity);
customizeSlider(thickness);
lines = new Line();
ghostV = 100;
thresholdV = 30;
velocityV = 1;
thicknessV = 2;
for(int i =0;i<dots.length;i++){
dots[i] = new Particle();
}
smooth();
}
void draw(){
noStroke();
fill(255,265-ghostV);
rect(0,0,width,470);
for(int i =0;i<dots.length;i++){
dots[i].display(thicknessV);
if(mousePressed){
dots[i].move();
dots[i].update(velocityV);
}
else{
dots[i].slowDown();
}
dots[i].checkEdges();
}
for(int i =0;i<dots.length;i++){
for(int j =i+1;j<dots.length;j++){
lines.display(dots[i],dots[j],thresholdV);
}
}
noStroke();
fill(0);
rect(0,470,720,106);
}
public void ghost(int v){
ghostV = v;
}
public void threshold(int v){
thresholdV = v;
}
public void velocity(int v){
velocityV = v;
}
public void thickness(int v){
thicknessV = v;
}
void customizeSlider(Slider inputSlider) {
inputSlider.setColorBackground(color(50));
inputSlider.setColorForeground(color(100));
inputSlider.setColorActive(color(150));
inputSlider.setColorLabel(color(255));
inputSlider.captionLabel().style().marginLeft = 5;
}
class Particle {
PVector [] location = new PVector[2];
PVector target,dir;
PVector velocity;
PVector acceleration;
float topSpeed;
float slowDownRate;
float velocityOffset;
int dotsize;
Particle() {
location[0] = new PVector(random(width),random(470));
location[1] = new PVector(location[0].x,location[0].y);
velocity = new PVector(0,0);
target = new PVector(location[0].x,location[0].y);
topSpeed = 8;
slowDownRate = random(0.7,0.99);
}
void update(float velocityOffsetInput) {
location[1].x = location[0].x;
location[1].y = location[0].y;
velocityOffset = velocityOffsetInput;
dir = PVector.sub(target,location[0]);
dir.normalize();
dir.mult(velocityOffset*random(0.5));
acceleration = dir;
velocity.add(acceleration);
velocity.limit(topSpeed);
location[0].add(velocity);
}
void move() {
target = new PVector(mouseX,mouseY,0);
}
void slowDown() {
location[1].x = location[0].x;
location[1].y = location[0].y;
velocity.mult(slowDownRate);
location[0].add(velocity);
}
void display(int dotsizeInput) {
dotsize = dotsizeInput;
strokeWeight(dotsize);
stroke(0,125);
line(location[0].x,location[0].y,location[1].x,location[1].y);
}
void checkEdges() {
if (location[0].x > width) {
velocity.x *= -1;
}
else if(location[0].x < 0) {
velocity.x *= -1;
}
if (location[0].y > 470) {
velocity.y *= -1;
}
else if(location[0].y < 0) {
velocity.y *= -1;
}
constrain(velocity.x,0,width);
constrain(velocity.y,0,470);
}
}
class Line{
Particle d1,d2;
int threshold;
Line(){
}
void display(Particle inputD1,Particle inputD2,int inputThreshold){
threshold = inputThreshold;
if(dist(inputD1.location[0].x,inputD1.location[0].y,inputD2.location[0].x,inputD2.location[0].y)<threshold){
strokeWeight(3-(dist(inputD1.location[0].x,inputD1.location[0].y,inputD2.location[0].x,inputD2.location[0].y)/threshold)*3);
stroke(0,255-(dist(inputD1.location[0].x,inputD1.location[0].y,inputD2.location[0].x,inputD2.location[0].y)/threshold)*255);
line(inputD1.location[0].x,inputD1.location[0].y,inputD2.location[0].x,inputD2.location[0].y);
}
}
}