这是一个很好看的草图。你对acc = d 是完全正确的。
这部分:
for (Node n: nodes) {
PVector d = PVector.sub(n.loc, loc);
d.normalize();
d.mult(n.strength);
acc = d;
}
表示您正在覆盖 d.acc 向量。
由于您运行循环,最终 acc 将等于列表中的最后一个节点。
如果想让每个节点都有一定的影响力,只需将基于节点的向量添加到acc即可:
for (Node n: nodes) {
PVector d = PVector.sub(n.loc, loc);
d.normalize();
d.mult(n.strength);
acc.add(d);
}
您已经在鼠标交互时这样做了。
就其他建议而言,您可以尝试更频繁地缓存 PVector 实例。下面我提供了一个如何缓存 mousePosition 的基本示例(作为单个顶级变量,而不是多个实例,每个粒子,每个帧)。 mag() 使用 sqrt(),这可能会很昂贵。尝试改用magSq()(并改用平方范围)。您可以在 Daniel Shiffman 的 chapter 6.15 A Few Last Notes: Optimization Tricks of Nature of Code 中发现这些。我强烈推荐这本书。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
PVector m = new PVector(mouseX, mouseY);
ArrayList<Particle> parts = new ArrayList<Particle>();
ArrayList<Node> nodes = new ArrayList<Node>();
float speed = 2;
float grav = 4;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
size(800, 800, P2D);
// fullScreen(P2D);
noStroke();
smooth(4);
blendMode(ADD);
frameRate(60);
for (int i = 0; i < 1000; i++) {
parts.add(new Particle(new PVector(random(width), random(height)), (int)random(1, 25)));
}
nodes.add(new Node(new PVector(200, 400), 0.75));
nodes.add(new Node(new PVector(400, 400), 0.50));
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void draw() {
background(0);
if(mousePressed){
m.set(mouseX, mouseY);
}
for (Node n: nodes) {
n.draw();
}
for (int i = 0; i < parts.size(); i++) {
Particle p = (Particle) parts.get(i);
p.draw();
p.boundary();
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Particle {
PVector loc, vel, acc;
int size = 5;
Particle(PVector loc, int size) {
this.loc = loc;
vel = new PVector();
acc = new PVector();
this.size = size;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void draw() {
acc.mult(0);
for (Node n: nodes) {
PVector d = PVector.sub(n.loc, loc);
d.normalize();
d.mult(n.strength);
//acc = d;
acc.add(d);
}
if (mousePressed && mouseButton == LEFT) {
PVector d = PVector.sub(m, loc);
//d.normalize();
d.setMag(map(d.mag(), 0, 2200, speed, 0));
d.mult(speed);
//acc = d;
acc.add(d);
} else if (mousePressed && mouseButton == RIGHT) {
PVector d = PVector.sub(m, loc);
d.normalize();
d.mult(-1*speed);
//acc = d;
acc.add(d);
}
acc.set(acc);
acc.mult(acc.mag());
vel.add(acc);
//vel.add(new PVector(0, grav));
loc.add(vel);
acc.mult(0);
//vel.mult(pow(0.90, 0.1*size));
vel.mult(0.97);
colorScheme(0);//"RedYellow"
ellipse(loc.x, loc.y, size, size);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void boundary() {
if(loc.x < 0)
vel.x *= -1;
if(loc.x > width)
vel.x *= -1;
if(loc.y < 0)
vel.y *= -1;
if(loc.y > height)
vel.y *= -1;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
String[] patterns = {"RedYellow","RedMagenta","GreenYellow","GreenCyan","BlueMagenta","BlueCyan","Cyclic","BWCyclic","PROTOTYPE"};
//void colorScheme(String pattern) {
void colorScheme(int pattern) {
//compute this once, rather than multiple times per case
//also check out magSq() https://processing.org/reference/PVector_magSq_.html
float mag = vel.mag();
switch (pattern) {
case 0:
fill(255, map(mag, 0, 20, 0, 255), map(mag - 20, 0, 20, 0, 255)); //Red Yellow White
break;
case 1:
fill(255, map(mag - 20, 0, 20, 0, 255), map(mag, 0, 20, 0, 255)); //Red Magenta White
break;
case 2:
fill(map(mag, 0, 20, 0, 255), 255, map(mag - 20, 0, 20, 0, 255)); //Green Yellow White
break;
case 3:
fill(map(mag - 20, 0, 20, 0, 255), 255, map(mag, 0, 20, 0, 255)); //Green Cyan White
break;
case 4:
fill(map(mag, 0, 20, 0, 255), map(mag - 20, 0, 20, 0, 255), 255); //Blue Magenta White
break;
case 5:
fill(map(mag - 20, 0, 20, 0, 255), map(mag, 0, 20, 0, 255), 255); //Blue Cyan White
break;
case 6:
fill(cos(map(mag, 0, 20, 0, 360))*255, cos(map(mag + 20/3, 0, 20, 0, 360))*255, cos(map(mag + 40/3, 0, 20, 0, 360))*255); //Cyclic
break;
case 7:
fill(cos(map(mag, 0, 20, 0, 360))*255, cos(map(mag, 0, 20, 0, 360))*255, cos(map(mag, 0, 20, 0, 360))*255); //B&W Cyclic
break;
case 8:
fill(0, 0, 0); //Cyclic
break;
default:
stroke(255, 255, 255);
fill(255, 255, 255);
break;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class Node {
PVector loc;
float strength;
Node(PVector loc, float strength) {
this.loc = loc;
this.strength = strength;
}
void draw() {
fill(255, 255, 255,64);
ellipse(loc.x, loc.y, 50, 50);
}
}