0

I have this small project that upon running the program it will automatically animate. In this case an oval shape should continuously animate using a thread. However in my program it will stop for the fifth direction - meaning following a certain path. Can anyone suggest me a better solution or help me let the oval shape continuously move until the user closes the program.

    package movingball;

    import java.awt.Color;
    import java.awt.Graphics;
    import javax.swing.JFrame;
    import javax.swing.JPanel;

    public class MovingBall extends JPanel{


    private int ballX = 30;
    private int ballY = 30;
    private int pattern = 1;
    private int limitHeight;
    private int limitWidth;
    boolean horizontalBoundary = true;
    boolean verticalBoundary = true;

    public MovingBall(){
        setBackground(Color.BLACK);
    }
    public MovingBall(int x, int y){
        x = this.ballX;
        y = this.ballY;  
        repaint();
    }
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500,700);

        MovingBall movingBall = new MovingBall();
        frame.add(movingBall);       
        frame.setVisible(true);

        BallUsingThread ball =  new BallUsingThread(movingBall);
        Thread first = new Thread(ball);

        first.start();

    }
    @Override
    public void paintComponent(Graphics canvas){
        super.paintComponent(canvas);

        canvas.setColor(Color.BLUE);
        canvas.fillOval(ballX, ballY, 100, 100);
    }

    public void animateBall(){

        if(horizontalBoundary && verticalBoundary){
            if(pattern == 1){
               diagonalDown(getWidth()-100,365); 

            }else if(pattern == 2){
               diagonalDown(getWidth(),150); 
            }
        }
        if(!horizontalBoundary && !verticalBoundary){          
            diagonalDownLeft(150, getHeight());
            pattern = 4;             
        } 
        if(horizontalBoundary && !verticalBoundary){           
            if(pattern == 4){
                diagonalUp(0, 490);
            } 
            if(pattern == 5){
                System.out.print("helo");
                diagonalUp(500,10);
            }
            System.out.print("last move" + pattern);
        }
        if(!horizontalBoundary && verticalBoundary){
            diagonalUpRight(getWidth(),100);
            pattern = 5;
            System.out.print(pattern);
        }
        repaint();
    }
    public void diagonalDown(int limitWidth, int limitHeight){
        this.limitWidth = limitWidth;
        this.limitHeight = limitHeight;

        if((ballX += 30) >= limitWidth){
            horizontalBoundary = false; 
        } 
        if((ballY += 30) >= limitHeight){
            verticalBoundary = false; 
        } 

    }
    public void diagonalUp(int limitWidth, int limitHeight){
        this.limitWidth = limitWidth;
        this.limitHeight = limitHeight;

        if((ballX -= 30) <= limitWidth) {
            horizontalBoundary = false;
        } 
        if((ballY -= 30) <= limitHeight){
            verticalBoundary = true;   
        } 
    }
    public void diagonalUpRight(int limitWidth, int limitHeight){
        this.limitWidth = limitWidth;
        this.limitHeight = limitHeight;

        if((ballX += 30) >= limitWidth) {
            horizontalBoundary = true;
        } 
        if((ballY -= 30) <= limitHeight){
            verticalBoundary = false;   
        }

    }
    public void diagonalDownLeft(int limitWidth, int limitHeight){
        this.limitWidth = limitWidth;
        this.limitHeight = limitHeight;

        if((ballX -= 30) <= limitWidth){
            horizontalBoundary = true;
        }
        if((ballY += 30) >= limitHeight){
            verticalBoundary = false;

        }
        //System.out.print("downleft");
    }

}

        class BallUsingThread implements Runnable{

        private final MovingBall movingBall;
        public BallUsingThread(MovingBall mb){
           movingBall = mb;
        }
        @Override
        public void run() {
            for(;;){
                movingBall.animateBall();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException ex) {
                    System.out.printf("Error",ex);
                }
            }      
        }   
    }
Bahramdun Adil
  • 5,907
  • 7
  • 35
  • 68
Jay Gorio
  • 335
  • 2
  • 4
  • 22
  • see http://stackoverflow.com/questions/7551069/update-ui-using-swingworker-thread?rq=1 –  Feb 29 '16 at 06:09
  • What happens in your code when `horizontalBoundary` and `verticalBoundary` both are true and `pattern` is 5? – Thomas Kläger Feb 29 '16 at 07:05

2 Answers2

0

It is not the problem with loop, if you System.out.println("loop running"); you will see that the loop is running, but that there is the problem with your draw ball logic that in this part of your code

if(!horizontalBoundary && verticalBoundary){
    diagonalUpRight(getWidth(),100);
    pattern = 5;
    System.out.print(pattern);
}

You are trying to diagonalUpRight() so after some calling to this method, then the none of the if clause will executed, because the conditions are not satisfied, so the ball remains in the same place at every loop, and seems that the loop stopped working.

A small suggestion: It is better to use while(tru /*some condition*/) loop instead of for(;;) in such cases.

Solution: If you carefully check the logic you will see that there is no an if clause which is used for the condition below:

horizontalBoundary = true
verticalBoundary = true

When pattern = 5 So when these two variables become true andpattern = 5 then nothing will happen to the ball position, so you can write a condition which is used to check these two variables for true value.

Eidt Eidt the below part of you code and you will see the result which loop is not stopping, I just initialized the position of ball the values become true and the pattern = 5.

if(horizontalBoundary && verticalBoundary){
   if(pattern == 1){
        diagonalDown(getWidth()-100,365); 

    }else if(pattern == 2){
         diagonalDown(getWidth(),150); 
    } else { // added this else block
          ballX = 30;
          ballY = 30;
          pattern = 1;
    }
}
Bahramdun Adil
  • 5,907
  • 7
  • 35
  • 68
0

Override paintComponent(Graphics) and implement all painting inside this method (but not animations).

Then use Swing timer to schedule periodic events each 100 ms, implement everything that changes the picture in the handler of this event and call repaint() from there at the end to refresh the picture.

Community
  • 1
  • 1
Audrius Meškauskas
  • 20,936
  • 12
  • 75
  • 93