Issue with using keyReleased() to pause row of moving ellipses

Hello! I posted this on StackOverflow, but don’t seem to be having any luck with answers, and would really appreciate some help please.

I’m having some trouble with a program I’m altering in Processing. This is the link to the original program: https://funprogramming.org/61-Draw-shaky-points-append-items-to-an-array.html

Basically what I’m attempting to do in my altered version is have a row of ellipses moving down the y axis of the screen. Then when the spacebar is pressed, that row freezes and another row appears to the right of the first row of ellipses (which are now paused and remain paused while the other row is now moving) and starts moving down the y axis of the screen. Then when the spacebar is pressed again that row pauses and another moving row appears to the right. This should keep happening again and again. What I’m struggling with is having the first row stop while the next row keeps moving. Any suggestions?

I tried doing the following bit of code, but that didn’t seem to do what I wanted.

x[0]++;

Also, there is currently only one ellipse at the beginning, but I would like there to be four ellipses moving down the screen in a row (one ellipse directly beneath the other). I’m assuming that I’d use a loop to do this, but I’m just not sure how to go about doing that. Any help would be very appreciated please!

This is the code I have so far:

int x[] = {}; 
int y[] = {}; 
boolean pause; 
int xPos; 
int yPos; 

void setup() { 
  size(500, 400); 
  background(255);
  pause = false; 
  xPos = 0; 
  yPos = 0; 
} 

void draw() { 
  if (pause) { 
      background(255); 
      for(int i = 0; i < x.length; i++) { 
          fill(0); 
          ellipse(x[i], y[i], 20, 20); 
          y[i] = y[i] + 1; 
      } 
   } 
} 

void keyReleased() { 
  if (key == ' ') { 
    pause = !pause; 
    xPos++; 
    yPos++; 
    x = append(x, xPos); 
    y = append(y, yPos); 
    x[0]++; 
  }
}

2 Likes

Is this what you’re looking for?

boolean pause;
int xPos, yPos, ellipseSize = 20;
int[] x = {}, y = {};

void setup() { 
  size(500, 400); 
  background(255);
} 

void draw() { 
  if (pause) { 
    background(255);
    fill(0); 

    for (int i = 0; i < x.length; i++) { 
      for (int j = 0; j < 4; j++) {
        ellipse(x[i], y[i] + ellipseSize * j, ellipseSize, ellipseSize);
      }
      
      y[i]++;
    }
  }
} 

void keyReleased() { 
  if (key == ' ') { 
    pause = !pause; 
    
    if (pause) {
      xPos += ellipseSize; 
      x = append(x, xPos); 
      y = append(y, yPos);
    }
  }
}

If so, I’ll explain what’s different about it. :smile:

1 Like

Thank you so much for responding! I really appreciate your help!

That’s almost what I need the program to do. However, the first row of ellipses should stay paused and then the next row that appears should be moving. Then when the spacebar is pressed again, that new moving row should also pause and another moving row should appear. Do you have any suggestions for keeping the rows paused please?

And yes, an explanation would be amazing thank you! No matter what I tried I couldn’t get it to work, so I would love to understand what you’ve done. Again, thank you so much for your response and help.

1 Like

You’re welcome! ;D
This should be what you need (explanation in comments):

// It's good practice to store stuff like this in variables,
// so when you want to change something, you only need to do it once.
final int ellipseSize = 20, rowSize = 4;

boolean pause;
int xPos, yPos;
int[] x = {}, y = {};

void setup() { 
  size(500, 400); 
  background(255);
} 

void draw() { 
  background(255);
  fill(0); 

  // We only want the moving to stop while paused, not the displaying.
  // This will be necessary if you want to display stuff not based on
  // whether paused is true or false.
  if (pause) {
    // Only move the last row.
    // (array.length - 1 corresponds to the last index of an array)
    y[y.length - 1]++;
  }

  // For every row...
  for (int i = 0; i < x.length; i++) { 
    for (int j = 0; j < rowSize; j++) {
      // Here we calculate the y value of each ellipse, by
      // adding ellipseSize * the iteration we're one to y[i].
      int realY = y[i] + ellipseSize * j;

      //... display an ellipse rowSize (4) times.
      ellipse(x[i], realY, ellipseSize, ellipseSize);
    }
  }
} 

void keyReleased() { 
  if (key == ' ') { 
    pause = !pause; 

    // Only do this on pausing (or alternatively unpausing)
    // so you don't add 2 rows.
    if (pause) {
      // Increment the xPos by ellipseSize, so that all rows are spaced out enough.
      xPos += ellipseSize;

      // Append the values.
      x = append(x, xPos); // Instead of xPos, you could simply use x.length * ellipseSize
      y = append(y, yPos);
    }
  }
}

Note: Once you’re done with this sketch, you might want to take a look at ArrayList, which basically does that x = append(x, ...) part for you with it’s add(...) method. Basically a resizable array.
You might also be interested in PVector, which is designed to store both an x and a y value. :wink:

2 Likes

Thank you so so so much! You have no idea how long I’ve been struggling with this. Thanks for your explanation as well. It really cleared things up for me.

I’ll take a look at ArrayList and PVector as well. I’ve read a bit about them on the Processing reference page but I’ll take a further look into them as they seem like they could be useful.

Sorry for the constant questions, I’m fairly new to Processing and so I’m still trying to understand some of the concepts and tend to struggle with some things. I had just one more question please if you’re willing to keep helping? I was just wondering what would you recommend to get the first row of ellipses to appear as soon as you run the program, rather than after you press the space key? i.e. as soon as you click the run button the first row of ellipses are there and moving down the screen.

Again, thanks so much for your help! It’s really given me a broader understanding of what I’m doing.

1 Like

Of course! It’s great that you have lots of questions! :smiley:

To do what you want to do, I would give xPos and x/y these default values:

int xPos = ellipseSize / 2, yPos;
int[] x = { xPos }, y = { 0 };

Now in order to let the rows move from the beginning, just change

if (pause) {
  y[y.length - 1]++;
}

to

if (!pause) { // Notice the extra !
  y[y.length - 1]++;
}

It makes more sense anyways. :wink:

1 Like

Ok, that mostly works. Except now the second row of ellipses starts off paused and doesn’t move until I press the spacebar, when instead they should just start moving as soon as the spacebar has been pressed. i.e. first row starts off moving as soon as the run button is pressed, spacebar is pressed and first row pauses, then second row appears and starts moving straight away with no input from spacebar.

I tried playing around with the code to come up with my own solution, but can’t seem to figure it out. Again, thank you so much for your help! I’m finally getting somewhere with this little project I started in order to learn more about Processing.

1 Like

Just get rid of pause and change your code accordingly:

if (!pause) {
  y[y.length - 1]++;
}

becomes

y[y.length - 1]++;

and change keyReleased to:

void keyReleased() { 
  if (key == ' ') { 
    // Increment the xPos by ellipseSize, so that all rows are spaced out enough.
    xPos += ellipseSize;

    // Append the values.
    x = append(x, xPos); // Instead of xPos, you could simply use x.length * ellipseSize
    y = append(y, yPos);
  }
}

if you want the row to appear as soon as a key is pressed rather than released, use keyPressed instead of keyReleased. :wink:

2 Likes

Thank you so so so much! That worked perfectly! Last question, I promise, but if I wanted the ellipses to bounce off the bottom of the screen instead of disappearing if I don’t press the space key, what would you recommend?

i.e. the run button is pressed, the first row of ellipses starts moving down the screen, the fourth ellipse in the first row reaches the bottom of the screen and then the row starts moving up the screen. Then when the first ellipse in the row hits the top of the screen, they start moving down again. Then the spacebar is pressed and the next row of ellipses appears and does the same thing. Then it continues like that. So basically the rows also bounce up and down the screen.

I tried:

if (realY >= height) || (realY <= 0)) {
   realY *= -1;
}

But that didn’t seem to do anything.

Also, the reason I went with keyReleased() and not keyPressed() is because I didn’t want the user to be able to hold the spacebar down and draw a whole bunch of ellipses at once.

So sorry again for the constant questions! I’m just trying to get a broader understanding of how Processing works and I’ve found that playing around with random animations that do a lot of different things really seems to help. Again, thank you for taking the time to help me! It is very much appreciated.

2 Likes

You’ll need to store the speed at which the ellipses move in a variable which you can reverese.

So at the top, introduce this variable:

int speed = 1;

Then, instead of always saying y[y.length - 1]++ and therefore incrementing by (+) 1, increment by speed instead and after doing so, reverse it if the ellipses are out of bounds.

  // Only move the last row.
  int index = y.length - 1;
  y[index] += speed;

  // h for height. If you wanted, you could also store this as a global
  // variable because the value won't change, or put the term inside
  // the if-statement.
  int h = ellipseSize * (rowSize - 1) + ellipseSize / 2;
  if (y[index] < yPos || y[index] + h >= height)
    speed = -speed;
2 Likes

Amazing! Thank you so so so much! It’s working exactly the way I want it to now and I finally understand what I’m doing. Can’t wait to implement what you’ve taught me in my next little Processing project. I really appreciate your help and the time you’ve taken to help me. Thank you!

2 Likes

You are very welcome! :smile: :stuck_out_tongue_winking_eye:

1 Like