Processing, ellipse not following alpha values?

2019-05-30 00:32发布

问题:

  class Particle{

  PVector velocity, location; //PVector variables for each particle.

  Particle(){ //Constructor - random location and speed for each particle.
    velocity = new PVector(random(-0.5,0.5), random(-0.5,0.5));
    location = new PVector(random(0,width),random(0,width));
  }

  void update() { location.add(velocity); } //Motion method.

  void edge() {  //Wraparound case for particles.
    if (location.x > width) {location.x = 0;} 
    else if (location.x < 0) {location.x = width;}

    if (location.y > height) {location.y = 0;}
    else if (location.y < 0) {location.y = height;}
  }

  void display(ArrayList<Particle> p){ //Display method to show lines and ellipses between particles.

    for(Particle other: p){ //For every particle in the ArrayList.
     float d = PVector.dist(location,other.location); //Get distance between any two particle.
     float a = 255 - d*2.5; //Map variable 'a' as alpha based on distance. E.g. if distance is high, d = 100, alpha is low, a = 255 - 225 = 30.

     println("Lowest distance of any two particle =" + d); //Debug output.

     if(d<112){ //If the distance of any two particle falls bellow 112.
      noStroke(); //No outline.
      fill(0,a); //Particle are coloured black, 'a' to vary alpha.
      ellipse(location.x, location.y, 8, 8); //Draw ellipse based on location of particle.

      stroke(0,a); //Lines are coloured black, 'a' to vary alpha.
      strokeWeight(0.7);
      line(location.x,location.y,other.location.x,other.location.y); //Draw line between four coordinates, between two particle.
     }

    }
  }
}

ArrayList<Particle> particles = new ArrayList<Particle>(); //Create a new arraylist of type Particle.

void setup(){
  size(640,640,P2D); //Setup frame of sketch.
  particles.add(new Particle()); //Add five Particle elements into arraylist.
  particles.add(new Particle());
  particles.add(new Particle());
  particles.add(new Particle());
  particles.add(new Particle());
}

void draw(){
 background(255); //Set white background.
 for(Particle p: particles){ //For every 'p' of type Particle in arraylist particles.
   p.update(); //Update location based on velocity.
   p.display(particles); //Display each particle in relation to other particles.
   p.edge(); //Wraparound if particle reaches edge of screen.
 }
}

In the above code, there are to shape objects, lines and ellipses. The transparency of which are affected by variable a.

Variable 'a', or alpha, is extrapolated from 'd' which is distance. Hence, when the objects are further, the alpha value of the objects falls.

In this scenario, the alpha values of the line do not change over time e.g. fade with distance. However the ellipses seem to be stuck on alpha '255' despite having very similar code.

If the value of 'a' is hardcoded, e.g.

if(d<112){ //If the distance of any two particle falls bellow 112.
      noStroke(); //No outline.

      fill(0,100); //Particle are coloured black, set alpha 'a' to be 100, grey tint.

      ellipse(location.x, location.y, 8, 8); //Draw ellipse based on location of particle.

the ellipses changes colour as expected to a grey tint.

Edit: I believe I have found the root of the issue. The variable 'a' does not discriminate between the particles that are being iterated. As such, the alpha might be stuck/adding up to 255.

回答1:

You're going to have to post an MCVE. Note that this should not be your entire sketch, just a few hard-coded lines so we're all working from the same code. We should be able to copy and paste your code into our own machines to see the problem. Also, please try to properly format your code. Your lack of indentation makes your code hard to read.

That being said, I can try to help in a general sense. First of all, you're printing out the value of a, but you haven't told us what its value is. Is its value what you expect? If so, are you clearing out previous frames before drawing the ellipses, or are you drawing them on top of previously drawn ellipses? Are you drawing ellipses elsewhere in your code?

Start over with a blank sketch, and add just enough lines to show the problem. Here's an example MCVE that you can work from:

stroke(0);
fill(0);
ellipse(25, 25, 25, 25);
line(0, 25, width, 25);

stroke(0, 128);
fill(0, 128);
ellipse(75, 75, 25, 25);
line(0, 75, width, 75);

This code draws a black line and ellipse, then draws a transparent line and ellipse. Please hardcode the a value from your code, or add just enough code so we can see exactly what's going on.

Edit: Thanks for the MCVE. Your updated code still has problems. I don't understand this loop:

for(Particle other: p){ //For every particle in the ArrayList.
     float d = PVector.dist(location,other.location); //Get distance between any two particle.
     float a = 255 - d*2.5; //Map variable 'a' as alpha based on distance. E.g. if distance is high, d = 100, alpha is low, a = 255 - 225 = 30.

     println("Lowest distance of any two particle =" + d); //Debug output.

     if(d<112){ //If the distance of any two particle falls bellow 112.
      noStroke(); //No outline.
      fill(0,a); //Particle are coloured black, 'a' to vary alpha.
      ellipse(location.x, location.y, 8, 8); //Draw ellipse based on location of particle.

      stroke(0,a); //Lines are coloured black, 'a' to vary alpha.
      strokeWeight(0.7);
      line(location.x,location.y,other.location.x,other.location.y); //Draw line between four coordinates, between two particle.
     }

    }
  }

You're saying for each Particle, you loop through every Particle and then draw an ellipse at the current Particle's location? That doesn't make any sense. If you have 100 Particles, that means each Particle will be drawn 100 times!

If you want each Particle's color to be based off its distance to the closest other Particle, then you need to modify this loop to simply find the closest Particle, and then base your calculations off of that. It might look something like this:

Particle closestNeighbor = null;
float closestDistance = 100000;

for (Particle other : p) { //For every particle in the ArrayList.

  if (other == this) {
    continue;
  }


  float d = PVector.dist(location, other.location);
  if (d < closestDistance) {
    closestDistance = d;
    closestNeighbor = other;
  }
}

Notice the if (other == this) { section. This is important, because otherwise you'll be comparing each Particle to itself, and the distance will be zero!

Once you have the closestNeighbor and the closestDistance, you can do your calculations.

Note that you're only drawing particles when they have a neighbor that's closer than 112 pixels away. Is that what you want to be doing?

If you have a follow-up question, please post an updated MCVE in a new question. Constantly editing the question and answer gets confusing, so just ask a new question if you get stuck again.