【问题标题】:Trouble with particle attraction using PVectors使用 Pvector 的粒子吸引问题
【发布时间】:2015-12-03 19:44:26
【问题描述】:

我正在处理 3.0 中制作粒子吸引器,并且在添加多个我认为是“节点”的东西时遇到了困难;无需鼠标输入即可自动吸引或排斥粒子的对象。通常左键单击鼠标会吸引这些粒子,右键单击会排斥它们。我制作了节点,以便我可以同时拥有多个吸引/排斥的位置。

我遇到的主要问题是当我添加多个节点时,只有最后添加的一个实际上有效;其他人什么都不做。

这是我所有的代码,包括另外两个类(粒子和节点)。代码很多,但如果有人能指出我的错误,我将不胜感激。

http://pastebin.com/iKELuVJ7

我认为问题出在我设置 acc = d 的 Node for 循环中的 Particle 类中,但我不知道一个好的解决方法。

作为一个额外的问题,有没有人知道一种使吸引力强度与与吸引物体的距离成反比的好方法?我尝试了一个具有任意上限/下限的向后map() 函数,该函数目前有效,但我不想对其进行硬编码。任何其他一般性改进/建议表示赞赏。

【问题讨论】:

标签: vector graphics processing particles


【解决方案1】:

这是一个很好看的草图。你对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);
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 2018-05-15
    • 2011-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多