How to use particles

edited April 2015 in How To...

So for a visualization of data I want a specific number of particles to move in a constrained area and then when the space bar is pressed move to another specific area and have the particles move in a different constrained space.

How would you do this and also change the number of particles in these constrained areas (go from 60 to 50).

Answers

  • edited April 2015 Answer ✓

    Start with nothing.

    void setup(){
      size(400,400);
    }
    
    void draw(){
      background(0);
    }
    

    Now add a Particle.

    class Particle{
      Particle(){
      }
    }
    

    Pretend you are the particle. What do you need to know about yourself? Maybe your position? Color?

    float px,py;
    color c;
    

    How do you know where you start?

    Particle(float ipx, float ipy, color ic){ px=ipx;py=ipy; c=ic; }
    

    How do you look? How do you move?

    void draw(){ fill(c); noStroke(); rect(px-1,py-1,2,2); }
    void move(){ px+=random(-1,1); py+=random(-1,1); }
    

    Do you exist?

    Particle p = new Particle(200,200,color(255));
    

    Do you have a chance at being?

    p.draw();
    

    There you are. Why don't you dance? Do you have friends?

    Particle[] ps = new Particle[2];
    

    Are your friends real?

    ps[0] = ...?
    

    Do they have a chance at being?

    for(int i=0; i< ...?
    

    Do they dance with you?

    ....??????
    
  • Great answer @TfGuy44 :)

  • How far did you get with it, @RifleGirl ? Do you have particles yet? Let's see the code you have now, and we can work on constraining them to areas.

  • edited April 2015

    @TfGuy44 This is kind of what I've got going right now... (not too much done......)

    Particle p = new Particle(200,200,color(255));
      int px=200;
      int py=200;
    
    void setup()
    {
      size(400,400);
    }
    
    void draw()
    {
      background(200);
      fill(0); 
      noStroke(); 
      rect(199,199,2,2);
    }
    
    void move()
    { 
      px+=random(-1,1); py+=random(-1,1); 
    }
    
    
    class Particle
    {
      //Global Variables
      float px,py;
      color c;
      //Defining Particles
      Particle(float ipx, float ipy, color ic)  
      { 
        px=ipx;
        py=ipy; 
        c=ic; 
      }
    }
    
  • Answer ✓

    Close. You have global variables px and py that you don't use - each Particle will have it's own copy of the px and py variables defined inside the class. The move() function you have is fine, but needs to be inside the Particle class too, since it's how a single Particle knows how to move. You're also missing a draw() method for your Particle class.

    Here, I've tidied things up a bit, and added a second particle so that you can see how the same class definition - class particle - can be used to make more than one object.

    // Name one Partcle, call it p0
    Particle p0;
    // And another, p1
    Particle p1;
    
    void setup() {
      size(400, 400);
      noStroke();
      // Create the named Particle p0
      p0 = new Particle(200, 200, color(255, 0, 0)); // p0 is red
      // And p1
      p1 = new Particle(200, 200, color(0, 0, 255)); // p1 is blue
    }
    
    void draw() {
      // Clear the scene
      background(0);
      // Move and draw p0
      p0.move();
      p0.draw();
      // Move and draw p1
      p1.move();
      p1.draw();
    }
    
    // This defines what a Particle object is.
    class Particle {
      // Memeber Variables (that each Particle will have)
      float px, py;
      color c;
      // Creates a Particle
      Particle(float ipx, float ipy, color ic) { 
        px=ipx;
        py=ipy; 
        c=ic;
      }
      // How a Particle moves
      void move() { 
        px+=random(-1, 1); 
        py+=random(-1, 1);
      }
      // How a Particle is drawn
      void draw() {
        fill(c);
        rect(px, py, 5, 5);
      }
    }
    

    The next step is to have an ARRAY of Particles, and create, move, and draw them using some for loops. And here's a hint: the Particle class doesn't need to change at all to do this! Try your hand at it, using the handy guide that @GoToLoop will now magically appear and post...

  • My guide? How about @PhiLho's?:
    http://forum.processing.org/two/discussion/8081/from-several-arrays-to-classes
    Especially the "Using the class" section! *-:)

  • @TfGuy44 Wow yeah that's definitely better... So now I am creating an array, is there a better way of going about the void draw() so that I don't have 50 p.draw and p.move?

  • Yes! Use a for loop!

  • edited April 2015

    If we got an array or any Iterable:
    http://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html

    we're illegible to choose what's known as the for-each (or enhanced) loop:

    1. http://docs.oracle.com/javase/8/docs/technotes/guides/language/foreach.html
    2. https://processing.org/reference/for.html

    In order to traverse/iterate over it! :-bd

    Let's say you've got a Particle[] array or an ArrayList<Particle>, which is an Iterable by the way,

    Particle[] particles = new Particle[100]; or ArrayList<Particle> particles = new ArrayList();

    1. https://processing.org/reference/Array.html
    2. https://processing.org/reference/ArrayList.html

    In either case you can use: for (Particle p : particles) p.script(); *-:)

  • @GoToLoop those are really helpful. I am trying to use some of the functions on the ArrayList html. I am basically trying to get the number of particles there should be from an existing array (there are 4 different numbers in each array so that the amount changes based on the mouse being clicked). The issue is there are 4 different arrays and the particles are supposed to be set up in 4 different areas. (I'm basically combining two of my "discussions" into one project haha)

    • @RifleGirl, I'm not getting what you mean. :(
    • AFAIK, a Particle class should contain every property needed to define a particle.
    • Supposedly you need 100 particles, you'd just declare an array w/ 100 slots:
      final Particle[] particles = new Particle[100];
    • Got no idea what are those other arrays you're talking about! ^#(^
    • You should post your most updated code so we can track your latest efforts!
  • edited April 2015

    @GoToLoop Haha sorry if I'm not clear. My particles are to show population growth and decline in 4 years in 4 different areas. So when you click the mouse the particles increase or decrease!

    Particle [] p = new Particle[50];
    
    int i=0;
    
    void setup() 
    {
      size(800, 800);
      noStroke();
      for (int j=0; j <p.length; j++)
      {
        p[j] = new Particle(400, 400, color(245, 175, 0));
      }
    }
    
    void draw() 
    {
      // Clear the scene
      background(0);
      for (int k = 0; k < p.length; k++)
      {
       p[k].move();
       p[k].draw();
      }
      textSize(60);
      fill(255); 
      text(years[i], 30, 600);
    }
    
    void mousePressed()
     {
        i++;
        if(i==4)
        {
          i=0;
        }
     }
    

    and then I have the number of particles I need in specific areas here

    int[] NE = new int[4];
    {
      NE[0] = 60;
      NE[1] = 55;
      NE[2] = 45;
      NE[3] = 46;
    }
    
    int[] ND = new int[4];
    {
      ND[0] = 80;
      ND[1] = 70;
      ND[2] = 40;
      ND[3] = 45;
    }
    
    int[] F = new int[4];
    {
      F[0] = 60;
      F[1] = 35;
      F[2] = 24;
      F[3] = 28;
    }
    
    int[] M = new int[4];
    {
      M[0] = 120;
      M[1] = 100;
      M[2] = 110;
      M[3] = 100;
    }
    
    //years to be used in the text
    int[] years = new int[4];
    {
      years[0] = 2000;
      years[1] = 2005;
      years[2] = 2010;
      years[3] = 2014;
    }
    

    My Particles class is here

    // This defines what a Particle object is.
    class Particle 
    {
      // Memeber Variables (that each Particle will have)
      float px, py;
      color c;
      // Creates a Particle
      Particle(float ipx, float ipy, color ic) 
      { 
        px=ipx;
        py=ipy; 
        c=ic;
      }
    
      void move() { 
        px+=random(-.1, .1); 
        py+=random(-.1, .1);
      }
    
      void draw() 
      {
        fill(c);
        ellipse(px, py, 2, 2);
      }
    }
    

    It is sounding though that I will need to make 4 different particle classes.

  • edited April 2015
    • So you have a buncha arrays which share the same index across.
    • According to this article I've mentioned before:
      http://forum.processing.org/two/discussion/8081/from-several-arrays-to-classes
    • You can encapsulate all the related arrays as properties of 1 class! *-:)
    • Let's call it Area for example.
    • Apart from year, I dunno what are the meaning of all those 4 other properties.
    • Nonetheless, here it goes: B-)


    // forum.processing.org/two/discussion/10300/how-to-use-particles
    
    class Area {
      final int y, ne, nd, f, m;
    
      Area(int $y, int $ne, int $nd, int $f, int $m) {
        y  = $y;
        ne = $ne;
        nd = $nd;
        f  = $f;
        m  = $m;
      }
    
      @ Override String toString() {
        return "Y: " + y + ", NE: " + ne +  ", ND: " + nd
          +  ", F: " + f +  ", M: " + m;
      }
    }
    
  • @GoToLoop So then to call the given number in an array and make that the number of particles that appear do you have to define that in the Particle class?

  • edited April 2015

    I believe you wish for a particular Area to control some amount of Particle objects, right?
    Then you need to include 1 array of Particle[] as an Area property as well:

    // forum.processing.org/two/discussion/10300/how-to-use-particles
    
    class Area {
      final int y, ne, nd, f, m;
      final Particle[] p;
    
      Area(int $yr, int $ne, int $nd, int $f, int $m) {
        yr = $yr;
        ne = $ne;
        nd = $nd;
        f  = $f;
        m  = $m;
    
        p  = new Particle[some_amount_you_wish];
    
        for (int i = 0; i != some_amount_you_wish; ++i)
          p[i] = new Particle(some_pos_x, some_pos_y, some_color);
      }
    
      @ Override String toString() {
        return "YR: " + yr + ", NE: " + ne +  ", ND: " + nd
          +   ", F: " + f  + ", M: "  + m
          +   ", P: " + p.length;
      }
    }
    
  • edited April 2015

    @GoToLoop I see what you're doing but can't seem to implement it. My main issue right now is that I cannot seem to call to the one array of numbers I have. I am trying to focus less on the areas now and just on one array of particles (just so I understand how to do that first, then I will try to tackle that problem).

    Particles [] p = new Particles[4];
    
    int i=0;
    
    void setup() 
    {
      size(800, 800);
      noStroke();
      ArrayList<Particles> particles = new ArrayList<Particles>();
      while(particles.size() < Population[0])
      {
        particles.add(new Particles(400,400,color(255,116,3)));
      }
      //p[i] = new Particle(400, 400, color(255,116,3));
    }
    
    void draw() 
    {
      // Clear the scene
      background(0);
      for(int j=0; j< particles.size(); j++)
      {
        particles.get(j).move();
        particles.get(j).draw();
      }
      textSize(60);
      fill(255); 
      text(years[i], 30, 600);
    }
    
    void mousePressed()
     {
        i++;
        if(i==4)
        {
          i=0;
        }
    
        if(particles.size() < Population[i])
        {
          while(particles.size()<Population[0])
          {
            particles.add(new Particles());
          }
        }
        if(Population[i] < particles.size())
        {
          while(Population[i] < particles.size())
          {
            particles.remove(new Particles());
          }
        }
     }
    
    int[] Population = new int[4];
    {
      Population[0] = 320;
      Population[1] = 260;
      Population[2] = 219;
      Population[3] = 200;
    }
    
    //years to be used in the text
    int[] years = new int[4];
    {
      years[0] = 2000;
      years[1] = 2005;
      years[2] = 2010;
      years[3] = 2014;
    }
    
    
    // This defines what a Particle object is.
    class Particles 
    {
      // Memeber Variables (that each Particle will have)
      float px, py;
      color c;
      // Creates a Particle
      Particles(float ipx, float ipy, color ic) 
      { 
        px=ipx;
        py=ipy; 
        c=ic;
      }
      // How a Particle moves
      void move() 
      { 
        px+=random(-2, 2); 
        py+=random(-2, 2);
      }
      // How a Particle is drawn
      void draw() 
      {
        fill(c);
        ellipse(px, py, 10, 10);
      }
    
    }
    

    I uploaded my new code, maybe you can see my problem? (also @TfGuy44) I figure there must be something I'm not seeing...

  • Sorry, I'm not listening. I was totally sidetracked and wrote this instead.

    ArrayList<Particle> parts = new ArrayList();
    float r;
    color k;
    float mx, my;
    color rcolor() { 
      return(color(random(255), random(255), random(255)));
    }
    
    void setup() {
      size(400, 400);
      ellipseMode(CENTER);
      for ( int i=0; i < 200; i++) {
        parts.add( new Particle( random(width), random(height), rcolor() ) );
      }
      noStroke();
    }
    
    void draw() {
      background(0);
      for ( int i=0; i < parts.size (); i++) {
        parts.get(i).draw();
      }
      if (mousePressed) {
        r++;
        fill(k, 10);
        stroke(k);
        ellipse(mx, my, r*2, r*2);
      }
    }
    
    void mousePressed() {
      mx=mouseX;
      my=mouseY;
      k = rcolor();
      r=0;
    }
    
    void mouseReleased() {
      for ( int i=0; i < parts.size (); i++) {
        parts.get(i).joinZone(mx, my, r, k);
      }
    }
    
    class Particle {
      float px, py, vx, vy;
      color c;
      boolean isZoned;
      float zx, zy, zr;
      color zc;
      Particle(float ipx, float ipy, color ic) { 
        px=ipx;
        py=ipy;
        vx = random(-1, 1);
        vy = random(-1, 1);
        c=ic;
        isZoned = false;
      }
    
      void move() {
        float tpx = px;
        float tpy = py; 
        px+=vx;//random(-1, 1); 
        py+=vy;//random(-1, 1);
        px+=width;
        py+=height;
        px%=width;
        py%=height;
        if (isZoned) {
          if (dist(px, py, zx, zy)>zr) {
            px = tpx;
            py = tpy;
            vx = random(-1, 1);
            vy = random(-1, 1);
          }
          if (dist(px, py, zx, zy)>zr) {
            if (px>zx)px--;
            if (px<zx)px++;
            if (py>zy)py--;
            if (py<zy)py++;
          }
        }
      }
      void draw() {
        move();
        fill(c);
        if (isZoned) fill(zc);
        noStroke();
        rect(px, py, 5, 5);
        //    if ( random(1) < 0.01 ) {
        //    isZoned = false;
        //}
      }
      void joinZone(float izx, float izy, float izr, color izc) {
        if (dist(px, py, izx, izy)<izr) {
          zx = izx;
          zy = izy;
          zr = izr;
          zc = izc;
          isZoned = true;
        }
      }
    }
    
Sign In or Register to comment.