Problem regarding ArrayList

edited May 2017 in Questions about Code

Hey,

Just wondering if anyone can help me out with this bit of code.

I'm trying to remove an ellipse that's drawn to the screen after I've clicked it. Not sure how to approach the problem?

ArrayList <ball> balls = new ArrayList <ball>();
int numOfBalls = 5;
float dist;

class ball {

  float x, y;

  ball() {

    x = random(20, width-20);
    y = random(20, height-20);
  }

  void draw_ball () {
    ellipse(x, y, 20, 20);
  }

  void remove_ball () {
    for (int i = numOfBalls-1; i >=0; i--) {

      dist = sqrt((x-mouseX) * (x-mouseX) + (y-mouseY) * (y-mouseY));
      if (dist <= 20) {

        balls.remove(i);
      }
    }
  }
}

void setup () {
  size(500, 500);
  for ( int i = 0; i < numOfBalls; i++)
    balls.add(new ball());
}

void draw () {
  for ( int i = 0; i < numOfBalls; i++)
    balls.get(i).draw_ball();
}

void mousePressed() {

  remove_ball();
}

Answers

  • edited May 2017

    In mousePressed for loop again over all ellipses but backward see reference on ArrayList

    Use dist to determine whether the ellipse is close mouse; if so use remove

  • Sorry i'm new to programming and I don't really know what i've done wrong >__<

    If I move the remove ball code to mouse pressed then I get errors

    ArrayList <ball> balls = new ArrayList <ball>();
    int numOfBalls = 5;
    float dist;
    
    class ball {
    
      float x, y;
    
      ball() {
    
        x = random(20, width-20);
        y = random(20, height-20);
      }
    
      void draw_ball () {
        ellipse(x, y, 20, 20);
      }
    
    }
    
    void setup () {
      size(500, 500);
      for ( int i = 0; i < numOfBalls; i++)
        balls.add(new ball());
    }
    
    void draw () {
      for ( int i = 0; i < numOfBalls; i++)
        balls.get(i).draw_ball();
    }
    
    void mousePressed() {
    
      for (int i = numOfBalls-1; i >=0; i--) {
    
        dist = sqrt((x-mouseX) * (x-mouseX) + (y-mouseY) * (y-mouseY));
        if (dist <= 20) {
          balls.remove(i);
        }
      }
    }
    
  • edited May 2017

    ... then I get errors.

    You need to be more specific than just saying I've got errors.
    Which 1? Which line has it occurred? =;

    Much probably the compiling error is about there are no x nor y variables within mousePressed(). 8-X
    The only x & y in your sketch are instance fields belonging to class ball. #-o

    BtW, classes & interfaces should follow the UpperCase naming convention.
    So it shoulda been named Ball rather than ball. :-B

    Now for a much cleaner solution: [-O<

    Let's declare 2 constants for your now Ball class, named DIAM & RAD.
    They're respectively the diameter & radius for Ball's ellipse():

    class Ball {
      static final int DIAM = 20, RAD = DIAM >> 1;
    
      float x = random(RAD, width  - RAD);
      float y = random(RAD, height - RAD);
    
      void display() {
        ellipse(x, y, DIAM, DIAM);
      }
    }
    

    After that, let's implement a new method to check whether the mouse's pointer is inside the Ball's ellipse().

    That is, point/circle collision check: http://JeffreyThompson.org/collision-detection/point-circle.php

    boolean isMouseWithinCircle() {
      return sq(mouseX - x) + sq(mouseY - y) < RAD * RAD;
    }
    

    Finally we can rewrite sketch's mousePressed() to take advantage of Ball's new method: :-bd

    void mousePressed() {
      for (int len = balls.size(), i = len; i-- != 0; )
        if (balls.get(i).isMouseWithinCircle()) {
          balls.set(i, balls.get(--len));
          balls.remove(len);
          redraw();
          return;
        }
    }
    
  • Thanks so much for the help ^:)^

    Just one more question,

    void isMouseWithinCircle() {
      return sq(mouseX - x) + sq(mouseY - y) < RAD * RAD;
    }
    

    This code is void, however you're returning a value? Is this supposed to be the case? as i'm getting an error when I copy it into my Ball class.

  • edited May 2017

    Oops! Forgot to declare that method returns a boolean value due to < operator. Sorry, fixed now! b-(
    https://Processing.org/reference/boolean.html
    https://Processing.org/reference/lessthan.html

  • Ughhh sorry i'm so nooby :|

    I'm getting a 'index out of bounds exception index 4 size 4' error when I click an ellipse.

    ArrayList <Ball> balls = new ArrayList <Ball>();
    int numOfBalls = 5;
    float dist;
    
    class Ball {
    
      static final int DIAM = 20, RAD = DIAM >>1;
      float x, y;
    
      Ball() {
    
        x = random(RAD, width-RAD);
        y = random(RAD, height-RAD);
      }
    
      boolean isMouseWithinCircle() {
      return sq(mouseX - x) + sq(mouseY - y) < RAD * RAD;
    }
    
      void draw_ball () {
        ellipse(x, y, DIAM, DIAM);
      }
    }
    
    void setup () {
      size(500, 500);
      for ( int i = 0; i < numOfBalls; i++)
        balls.add(new Ball());
    }
    
    void draw () {
      for ( int i = 0; i < numOfBalls; i++)
        balls.get(i).draw_ball();
    }
    
    void mousePressed() {
      for (int len = balls.size(), i = len; i-- != 0; )
        if (balls.get(i).isMouseWithinCircle()) {
          balls.set(i, balls.get(--len));
          balls.remove(len);
          redraw();
          return;
        }
    }
    
  • edited May 2017 Answer ✓

    Within draw(), at its for ( ; ; ) loop, the conditional is checking against numOfBalls.

    However, once remove() is executed, numOfBalls doesn't match balls's size() anymore: :|
    http://docs.Oracle.com/javase/8/docs/api/java/util/Collection.html#size--

    My proposal fix is to use an enhanced for ( : ) instead of a regular for ( ; ; ) loop: L-)
    https://Processing.org/reference/for.html

    So you don't need to worry about balls's current size() there: *-:)

    void draw() {
      background(#FFFF00);
      for (final Ball b : balls)  b.draw_ball();
    }
    
  • Thanks so much man @-)

    It's all working spick and span now :>

  • edited April 2018

    Posted your full & refactored sketch online. Check it out at the link below: :bz
    http://studio.SketchPad.cc/sp/pad/view/ro.PKnDDqu1vYo/latest

    /**
     * Clickable Balls (v1.0.1)
     * Jcov (2017-May-20)
     * Mod GoToLoop
     *
     * Forum.Processing.org/two/discussion/22678/
     * problem-regarding-arraylist#Item_9
     *
     * Studio.SketchPad.cc/sp/pad/view/ro.PKnDDqu1vYo/latest
     */
    
    import java.util.List;
    static final int BALLS = 10;
    final List<Ball> balls = new ArrayList<Ball>();
    
    void setup() {
      size(500, 500);
      smooth(3);
      noLoop();
    
      colorMode(RGB);
      ellipseMode(CENTER);
      strokeWeight(1.5);
      stroke(#00FFFF);
      fill(#0000FF);
    }
    
    void draw() {
      background(#FF00A0);
      if (balls.isEmpty())  makeBalls();
      for (final Ball b : balls)  b.display();
    }
    
    void mousePressed() {
      for (int len = balls.size(), i = len; i-- != 0; )
        if (balls.get(i).isMouseWithinCircle()) {
          balls.set(i, balls.get(--len));
          balls.remove(len);
          redraw();
          return;
        }
    }
    
    void makeBalls() {
      balls.clear();
      for (int i = 0; i++ < BALLS; balls.add(new Ball()));
    }
    
    static final int sq(final int n) {
      return n*n;
    }
    
    class Ball {
      static final int DIAM = 20;
      static final int RAD = DIAM >> 1;
      static final int RAD_SQ = RAD * RAD;
    
      short x = (short) round(random(RAD, width  - RAD));
      short y = (short) round(random(RAD, height - RAD));
    
      void display() {
        ellipse(x, y, DIAM, DIAM);
      }
    
      boolean isMouseWithinCircle() {
        return sq(mouseX - x) + sq(mouseY - y) < RAD_SQ;
      }
    }
    
  • edited May 2017

    Bonus sketch: a p5.js version too: :-bd
    http://p5js.SketchPad.cc/sp/pad/view/ro.CaQVvhrEKxAeXd/latest

    /**
     * Clickable Balls (v1.0)
     * Jcov (2017-May-21)
     * Mod GoToLoop
     *
     * forum.Processing.org/two/discussion/22678/
     * problem-regarding-arraylist#Item_10
     *
     * p5js.SketchPad.cc/sp/pad/view/ro.CaQVvhrEKxAeXd/latest
     */
    
    "use strict";
    
    const BALLS = 10, balls = [];
    let bg;
    
    function setup() {
      createCanvas(500, 500);
      noLoop();
    
      ellipseMode(CENTER).colorMode(RGB);
      fill('blue').stroke('cyan').strokeWeight(1.5);
    
      bg = color('#F0A');
    }
    
    function draw() {
      background(bg);
      balls.length || makeBalls();
      for (const b of balls)  b.display();
    }
    
    function mousePressed() {
      for (let i = balls.length; i--; )
        if (balls[i].isMouseWithinCircle()) {
          const tail = balls.pop();
          if (i !== balls.length)  balls[i] = tail;
          redraw();
          break;
        }
      return false;
    }
    
    function makeBalls() {
      balls.length = 0;
      for (let i = 0; i++ < BALLS; balls.push(new Ball));
    }
    
    class Ball {
      constructor() {
        this.x = round(random(Ball.RAD, width  - Ball.RAD));
        this.y = round(random(Ball.RAD, height - Ball.RAD));
      }
    
      display() {
        ellipse(this.x, this.y, Ball.DIAM);
      }
    
      isMouseWithinCircle() {
        return sq(mouseX - this.x) + sq(mouseY - this.y) < Ball.RAD_SQ;
      }
    }
    
    Ball.DIAM = 20;
    Ball.RAD = Ball.DIAM >> 1;
    Ball.RAD_SQ = Ball.RAD * Ball.RAD;
    
  • Awesome :P

Sign In or Register to comment.