Results 1 to 17 of 17
  1. #1
    jls7884 is offline Member
    Join Date
    Nov 2016
    Posts
    22
    Rep Power
    0

    Default Setting a random radius for a ball when using a button

    I am currently working on a bouncy ball program where I add balls and they bounce around the window. I am attempting to assign a random radius to the balls instead of a fixed one. It works when I initially start the program but not when I add an additional ball. Anyone know why that would be?

    Java Code:
    import javax.swing.Timer;
    import java.util.ArrayList;
    import java.awt.*;
    import javax.swing.*;
    import java.awt.event.*;
    import java.util.Random;
    
    public class BouncyBall extends JApplet {
      public BouncyBall() {
          @SuppressWarnings("OverridableMethodCallInConstructor")
          Component add = add(new BallControl());
      }
    
      /** Main method
         * @param args */
      public static void main(String[] args) {
        JFrame frame = new JFrame();
        JApplet applet = new BouncyBall();
        frame.add(applet);
        frame.setTitle("BouncyBall");
        frame.setLocationRelativeTo(null); // Center the frame
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 200);
        frame.setLocationRelativeTo(null); // Center the frame
        frame.setVisible(true);
      }
    }
    
    class BallControl extends JPanel {
      private BallPanel ballPanel = new BallPanel();
      private final JButton jbtSuspend = new JButton("Suspend");
      private final JButton jbtResume = new JButton("Resume");
      private final JButton jbtAdd = new JButton("+1");
      private final JButton jbtSubtract = new JButton("-1");
      private JScrollBar jsbDelay = new JScrollBar();
    
      @SuppressWarnings("OverridableMethodCallInConstructor")
      public BallControl() {
        // Group buttons in a panel
        JPanel panel = new JPanel();
        panel.add(jbtSuspend);
        panel.add(jbtResume);
        panel.add(jbtAdd);
        panel.add(jbtSubtract);
    
        // Add ball and buttons to the panel
        ballPanel.setBorder(new javax.swing.border.LineBorder(Color.red));
        jsbDelay.setOrientation(JScrollBar.HORIZONTAL);
        ballPanel.setDelay(jsbDelay.getMaximum());
        setLayout(new BorderLayout());
        add(jsbDelay, BorderLayout.NORTH);
        add(ballPanel, BorderLayout.CENTER);
        add(panel, BorderLayout.SOUTH);
    
        // Register listeners
        jbtSuspend.addActionListener(new Listener());
        jbtResume.addActionListener(new Listener());
        jbtAdd.addActionListener(new Listener());
        jbtSubtract.addActionListener(new Listener());
        jsbDelay.addAdjustmentListener((AdjustmentEvent e) -> {
            ballPanel.setDelay(jsbDelay.getMaximum() - e.getValue());
        });
      }
      
      class Listener implements ActionListener {
          @Override
    	  public void actionPerformed(ActionEvent e) {
    	    if (e.getSource() == jbtSuspend) {
    	      ballPanel.suspend();
    	    }
    	    else if (e.getSource() == jbtResume) {
    	      ballPanel.resume();
    	    }
    	    else if (e.getSource() == jbtAdd) {
    	      ballPanel.add();
    	    }
    	    else if (e.getSource() == jbtSubtract) {
    	      ballPanel.subtract();
    	    }
    	  }
      }
    }
    
    class BallPanel extends JPanel {
      private int delay = 10;
    
      // Create a timer with delay 1000 ms
      protected Timer timer = new Timer(delay, new TimerListener());
    
      private final ArrayList<SingleBall> list = new ArrayList<>();
        
        Random r = new Random();
        private final int radius = r.nextInt(30) + 5;
      
      public BallPanel() {
        timer.start();
      }
    
      public void add() {
        list.add(new SingleBall());
      }
    
      public void subtract() {
        if (list.size() > 0)
          list.remove(list.size() - 1); // Remove the last one
      }
    
      class TimerListener implements ActionListener {
        @Override /** Handle the action event */
        public void actionPerformed(ActionEvent e) {
          repaint();
        }
      }
    
      @Override
      protected void paintComponent(Graphics g) {
        super.paintComponent(g);
    
        for (int i = 0; i < list.size(); i++) {
          SingleBall ball = list.get(i);
          g.setColor(ball.color);
    
          // Check boundaries
          if (ball.x < 0 || ball.x > getWidth()) {
            ball.dx = -ball.dx;
          }
          
          if (ball.y < 0 || ball.y > getHeight()) {
            ball.dy = -ball.dy;
          }
    
          // Adjust ball position
          ball.x += ball.dx;
          ball.y += ball.dy;
          g.fillOval(ball.x - radius, ball.y - radius, radius * 2, radius * 2);
        }
      }
    
      public void suspend() {
        timer.stop(); // Suspend clock
      }
    
      public void resume() {
        timer.start(); // Resume clock
      }
    
      public void setDelay(int delay) {
        this.delay = delay;
        timer.setDelay(delay);
      }
    }
    
    class SingleBall {
      int x = 0;
      int y = 0; // Current ball position
      int dx = 2; // Increment on ball's x-coordinate
      int dy = 2; // Increment on ball's y-coordinate
      Color color = new Color(
          (int)(Math.random() * 256), (int)(Math.random() * 256),
          (int)(Math.random() * 256));
    }

  2. #2
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    13,541
    Rep Power
    26

    Default Re: Setting a random radius for a ball when using a button

    I can't see where you are adding a ball.

    It would be simpler if your SingleBall class held all the data for a ball, including the radius.
    It would also be easier to debug if you made all the values private, and created a move method on the ball, so the ball is responsible for moving. That would probably need the height and width passed into it.

    At the moment you seem to have a single radius for all balls.
    Please do not ask for code as refusal often offends.

    ** This space for rent **

  3. #3
    jls7884 is offline Member
    Join Date
    Nov 2016
    Posts
    22
    Rep Power
    0

    Default Re: Setting a random radius for a ball when using a button

    Okay. My add method calls the SingleBall class when the +1 button is pushed. If I were to set the radius in the SingleBall class what would I have to do to use the field in my PaintComponent Method?

  4. #4
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    Eastern Florida
    Posts
    20,001
    Rep Power
    33

    Default Re: Setting a random radius for a ball when using a button

    If I were to set the radius in the SingleBall class what would I have to do to use the field in my PaintComponent Method?
    If the radius were in the SingleBall class then the paintComponent method could get it the same way it gets the ball's x,y location.
    If you don't understand my response, don't ignore it, ask a question.

  5. #5
    jim829 is offline Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    6,226
    Rep Power
    13

    Default Re: Setting a random radius for a ball when using a button

    And it's best practice to make your class fields private and use getters and setters to get and set them.
    Initial settings can be accomplished thru a constructor (like the color and radius which are set randomly).

    Regards,
    Jim
    The JavaTM Tutorials | SSCCE | Java Naming Conventions
    Poor planning on your part does not constitute an emergency on my part

  6. #6
    jls7884 is offline Member
    Join Date
    Nov 2016
    Posts
    22
    Rep Power
    0

    Default Re: Setting a random radius for a ball when using a button

    It still won't work when the button is pressed. just for the initial startup. I don't think I'm understanding exactly what my code is doing. Here is what I have come up with now.

    I generate a random radius in my SingleBall class like this:
    Java Code:
    Random r = new Random();
      private final int ballRad = r.nextInt(20) + 5; 
      
      public int getRadius(){
         return this.ballRad;
      }
    I then create an instance of SingleBall in my BallPanel class and call the getRadius() method:
    Java Code:
    SingleBall rad = new SingleBall();
      int radius = rad.getRadius();
    I create the new variable radius to allow the field to be passed through the paintComponent method here:
    Java Code:
    g.fillOval(ball.x - radius, ball.y - radius, radius * 2, radius * 2);
    Then comes my add method:
    Java Code:
    public void add() {
        list.add(new SingleBall());
      }
    The add method is called in the action event where the +1 button is clicked which also calls the SingleBall class. Shouldn't it generate a new random integer and set the radius each time the button is used?

  7. #7
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    Eastern Florida
    Posts
    20,001
    Rep Power
    33

    Default Re: Setting a random radius for a ball when using a button

    The fillOval method needs to use the radius value from the ball object reference just like it uses the x and y values: ball.radius
    The random value for the radius needs to be stored in the SingleBall class, just like the x and y values.

    Suggestion: For more interesting ball movements, have the x,y,dx,dy values in SingleBall be randomly generated.
    Last edited by Norm; 11-11-2016 at 10:35 PM.
    If you don't understand my response, don't ignore it, ask a question.

  8. #8
    jim829 is offline Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    6,226
    Rep Power
    13

    Default Re: Setting a random radius for a ball when using a button

    Seems like it should work. But you might wan to show your code because there must be a glitch. I presume you are getting the radius
    from the SingleBall instance in the paintComponent method.

    Also, your boundary tests could use some work. I would think the ball should bounce as soon as the leading edge hits the edge of
    the frame.

    Regards,
    Jim
    Last edited by jim829; 11-11-2016 at 10:35 PM.
    The JavaTM Tutorials | SSCCE | Java Naming Conventions
    Poor planning on your part does not constitute an emergency on my part

  9. #9
    jls7884 is offline Member
    Join Date
    Nov 2016
    Posts
    22
    Rep Power
    0

    Default Re: Setting a random radius for a ball when using a button

    That makes sense. I made it even simpler. Just used the instance of SingleBall that I already created in the paintComponent method and just called the getRadius method directly in my fillOval method. Didn't need to create a new instance outside of the method. It does what I want it to now. Thank you. Also on your note Norm. that's an interesting idea. Might try to implement that.
    Last edited by jls7884; 11-11-2016 at 11:00 PM.

  10. #10
    jim829 is offline Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    6,226
    Rep Power
    13

    Default Re: Setting a random radius for a ball when using a button

    One more tidbit of information. The Graphics class was introduced in Java 1. Graphics2D in Java 2. Graphics2D subclass' the former but
    for compatibility, the super class, Graphics, is passed to the paint routines. This means you can do the following:
    Java Code:
    Graphics2D g2d = (Graphics2D) g; // where g is the passed Graphics instance.
    Why am I telling you this? Notice how rough the balls look on the edges. You can smooth them out using anti-aliasing.
    Insert the following somewhere before you fill the ovals.

    Java Code:
    Graphics2D g2d = (Graphics2D) g;
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
    Check out the API for other Graphics2D features.

    Regards,
    Jim
    The JavaTM Tutorials | SSCCE | Java Naming Conventions
    Poor planning on your part does not constitute an emergency on my part

  11. #11
    jls7884 is offline Member
    Join Date
    Nov 2016
    Posts
    22
    Rep Power
    0

    Default Re: Setting a random radius for a ball when using a button

    Thanks for that info jim. Had no idea that was a feature. I will definitely look into the other features as well when I get the chance.

  12. #12
    jls7884 is offline Member
    Join Date
    Nov 2016
    Posts
    22
    Rep Power
    0

    Default Re: Setting a random radius for a ball when using a button

    Norm. For the idea of randomly generating the x,y,dx, and dy values. Is there a range that you would recommend for the random generators or is any fine? Should I just experiment?

    EDIT:

    Just testing some values there seems to be a bit of lag with the slower speeds. Less noticeable when faster. Some also get stuck in the top left corner and some go along the left or top edge. Any way to eliminate that?
    Last edited by jls7884; 11-11-2016 at 11:32 PM.

  13. #13
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    Eastern Florida
    Posts
    20,001
    Rep Power
    33

    Default Re: Setting a random radius for a ball when using a button

    Try some more experimenting.

    What are the x,y,dx,dy values for the ones that get stuck or go along the edges?
    Last edited by Norm; 11-12-2016 at 10:19 PM.
    If you don't understand my response, don't ignore it, ask a question.

  14. #14
    jls7884 is offline Member
    Join Date
    Nov 2016
    Posts
    22
    Rep Power
    0

    Default Re: Setting a random radius for a ball when using a button

    The ones that get stuck would be when x,y,dx,dy are 0 and they move along the axis at dx=1 or dy=1. Adding 2 to dx and dy solved the issue. The movement changes drastically with high dx and dy values. That is why it appeared to have lag at slower speeds. Solved that by using a small range for dx and dy.

  15. #15
    Norm's Avatar
    Norm is offline Moderator
    Join Date
    Jun 2008
    Location
    Eastern Florida
    Posts
    20,001
    Rep Power
    33

    Default Re: Setting a random radius for a ball when using a button

    Sounds like you are making progress.
    If you don't understand my response, don't ignore it, ask a question.

  16. #16
    jim829 is offline Senior Member
    Join Date
    Jan 2013
    Location
    Northern Virginia, United States
    Posts
    6,226
    Rep Power
    13

    Default Re: Setting a random radius for a ball when using a button

    You might want to set dx and dy to 1 and make your speed slider logarithmic.

    Regards,
    Jim
    The JavaTM Tutorials | SSCCE | Java Naming Conventions
    Poor planning on your part does not constitute an emergency on my part

  17. #17
    jls7884 is offline Member
    Join Date
    Nov 2016
    Posts
    22
    Rep Power
    0

    Default Re: Setting a random radius for a ball when using a button

    It does what I want it to for now. I may come back and revisit this project in the future but for now I need to move on to a new project. Thanks for all the help and advice.

Similar Threads

  1. Radio Button Random Number Generator
    By Inferna in forum Android
    Replies: 7
    Last Post: 06-14-2013, 07:43 PM
  2. Radio Button Random Number Generator
    By Inferna in forum Android
    Replies: 1
    Last Post: 06-14-2013, 07:42 PM
  3. Setting a picture on a button
    By tomhcole in forum New To Java
    Replies: 2
    Last Post: 09-26-2008, 03:30 AM
  4. Problem deleting ball from bouncing ball app
    By adlb1300 in forum New To Java
    Replies: 2
    Last Post: 12-03-2007, 09:08 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •