Loading...
Logo
Processing Forum
Hi, all

Thanks in advance, I am having some custom class object stored in an ArrayList. When I click any of them, it will fade away and when alpha reaches 0, it will remove itself from the ArrayList using remove(this). However, if I click them in order, the moment when it is removed causing the rendering of the next object in ArrayList to flicker a bit. It almost seems like the ArrayList lost the next object for a brief moment so it wasn't updated and drawn to the screen. How do I go around and keep that flickering from happening?

In the code below, if you click starting with the bottom-right one and go clockwise, you will see the next object flicker. I am using Processing 2.0b8 on PC, and it happens with or without P2D

*just test it this on 1.5.1, also does it.
*just test it this on a Mac, also does it.
Copy code
  1. ArrayList<enemy> enemies;
  2. void setup() {
  3.   size(300,300, P2D);
  4.   enemies= new ArrayList<enemy>();
  5.   float a = PI/4; //create four enemies, PI/2 away, starting bottom-right corner
  6.   for (int i=0; i<4; i++) {
  7.     enemy temp = new enemy(width/2+100*cos(a), height/2+100*sin(a));
  8.     enemies.add(temp);
  9.     a+=PI/2;
  10.   }
  11. }
  12. void draw() {
  13.   background(0);
  14.   if (!enemies.isEmpty()) {
  15.     for (int i=0; i<enemies.size(); i++) {
  16.       enemy temp= enemies.get(i);
  17.       temp.update();
  18.     }
  19.   }
  20. }

  21. class enemy {
  22.   PVector pos;
  23.   float size;
  24.   boolean death;
  25.   int alpha;//alpha for all the color in the drawing of the enemy
  26.   int type;//enemy type
  27.     enemy(float _x, float _y) {
  28.     pos=new PVector(_x, _y);
  29.     size=60;
  30.     death = false;
  31.     alpha = 255;
  32.   }
  33.   void update() {
  34.     if (death) {//if dead, fade away
  35.       alpha-=5;
  36.       if (alpha<=0) {
  37.         enemies.remove(this);
  38.       }
  39.     }
  40.     if (mousePressed) {
  41.       if (mouseX>pos.x-size/2 && mouseX<pos.x+size/2) {
  42.         if (mouseY>pos.y-size/2 && mouseY<pos.y+size/2) {
  43.           damage();
  44.         }
  45.       }
  46.     }
  47.     //draw the enemy
  48.     pushMatrix();
  49.     translate(pos.x, pos.y);
  50.     fill(211, 127, 28, alpha);
  51.     ellipse(0, 0, size, size);
  52.     popMatrix();
  53.   }
  54.   void damage() {
  55.     death = true;
  56.   }
  57. }

Replies(3)

The problem is caused because you are removing the enemy while iterating over the ArrayList. If you remove number 1 then the ones after it in the list move down one space 2>1 3>2 etc. but the loop counter is incremented so the next drawn is at position 2 effectively it skipd drawing a circle for one frame giving the flicker.

The code below fixes the problem.

Copy code
  1. import java.util.*; // I added this for the Iterator
  2. ArrayList<enemy> enemies;

  3. void setup() {
  4.   size(300,300, P2D);
  5.   enemies= new ArrayList<enemy>();
  6.   float a = PI/4; //create four enemies, PI/2 away, starting bottom-right corner
  7.   for (int i=0; i<4; i++) {
  8.     enemy temp = new enemy(width/2+100*cos(a), height/2+100*sin(a));
  9.     enemies.add(temp);
  10.     a+=PI/2;
  11.   }
  12. }

  13. void draw() {
  14.   background(0);
  15.   if (!enemies.isEmpty()) {
  16.     for (Iterator<enemy> iter = enemies.iterator(); iter.hasNext();) {
  17.       enemy temp = iter.next();
  18.       if(temp.update())
  19.       iter.remove();
  20.     }
  21.   }
  22. }

  23. class enemy {
  24.   PVector pos;
  25.   float size;
  26.   boolean death;
  27.   int alpha;//alpha for all the color in the drawing of the enemy
  28.   int type;//enemy type
  29.     enemy(float _x, float _y) {
  30.     pos=new PVector(_x, _y);
  31.     size=60;
  32.     death = false;
  33.     alpha = 255;
  34.   }

  35.     // This no longer removes the enemy but returns true if it needs removing
  36.   boolean update() {
  37.     boolean toremove = false;
  38.     if (death) {//if dead, fade away
  39.       alpha-=5;
  40.       if (alpha<=0) {
  41.         toremove = true;
  42.        }
  43.     }
  44.     if (mousePressed) {
  45.       if (mouseX>pos.x-size/2 && mouseX<pos.x+size/2) {
  46.         if (mouseY>pos.y-size/2 && mouseY<pos.y+size/2) {
  47.           damage();
  48.         }
  49.       }
  50.     }
  51.     //draw the enemy
  52.     pushMatrix();
  53.     translate(pos.x, pos.y);
  54.     fill(211, 127, 28, alpha);
  55.     ellipse(0, 0, size, size);
  56.     popMatrix();
  57.     return toremove;
  58.   }
  59.  
  60.   void damage() {
  61.     death = true;
  62.   }
  63. }

Here's an alternative version which uses a backwards loop in place of an additional Iterator:
Copy code
    void draw() {
      background(0);
    
      for (int i = enemies.size(); i != 0;)
        if ( enemies.get(--i).update() )  enemies.remove(i);
    }