0

Red ball from this pointI am trying to make some animation in which a ball is falling from some height. During the fall, ball immediately gets to the bottom of the screen. So, to make it like a natural free falling object I tried adding delay using Thread.sleep(1000) inside the while loop. But as I added this delay( ), my whole program is freezing. Also the ball does not fall and even the close operation of the screen is deactivated. NOTE: For Thread.delay( ) , I had to put it in try/catch block. When this try/catch block and thread.delay() statements are removed, the program runs finely. In nutshell, all I want is to add delay during the falling of ball. NOTE : In my code below, I have added different System.out.println() statements just to check which part of the program is running and which is not. So, you can ignore that.

import java.awt.Color;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;


public class Resume extends JFrame
{
JLabel ball , hanger ;
int flag = 0 ;



public Resume(String title)
{
    super(title);


    hanger = new JLabel(new ImageIcon("crane-hanger.jpg"));
    hanger.setBounds(0 , -200 , 600 , 600 );
    hanger.setVisible(true);
    //hanger.setSize(100, 100);

    ball = new JLabel(new ImageIcon("snooker-red-ball.png"));
    ball.setBounds(10 , 60 , 400 , 400 );
    ball.setVisible(true);
    ball.isOptimizedDrawingEnabled();
    ball.requestFocusInWindow();
    //ball.requestFocus();
    addKeyListener(new KeyAdapter() 
    {
        public void keyPressed(KeyEvent k)
        {
        /*  if(k.getKeyCode() == KeyEvent.VK_DOWN)
            {
                ball.setLocation(ball.getX(), ball.getY()+ 10 );
                repaint();
            }
            if(k.getKeyCode() == KeyEvent.VK_UP)
            {
                ball.setLocation(ball.getX(), ball.getY()-10);
                repaint();
            }*/
            if(k.getKeyCode() == KeyEvent.VK_LEFT)
            {
                if(flag == 1)
                {
                    ball.removeKeyListener(this);
                }
                else
                {
                    ball.setLocation(ball.getX()-10, ball.getY());
                    repaint();
                }
            }
            if(k.getKeyCode() == KeyEvent.VK_RIGHT)
            {
                if(ball.getX()>=400)
                {
                    ball.removeKeyListener(this);
                    System.out.println(ball.getY());
                    ball_fall();

                }
                else
                {
                    ball.setLocation(ball.getX()+10, ball.getY());
                    repaint();
                }
            }

        }
    });



    setLayout(null);
    setSize(this.getMaximumSize());
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    //setResizable(false);
    setVisible(true);
    //setBackground(Color.black);
    //requestFocus();
    System.out.println("fall");
    getContentPane().add(ball);
    getContentPane().add(hanger);
    //add(l);
}

public void ball_fall()
{
    System.out.println("Ball falling");
    try
    {
        while(ball.getY()!= 400)
        {
            ball.setLocation(ball.getX(), ball.getY()+100);
            Thread.sleep(100);
            repaint();
            System.out.println("while falling");
        }
        flag = 1 ;
    }
    catch(Exception e)
    {
        System.out.println(e);
    }

}
public static void main(String args[])
{
    Resume r = new Resume("RESUME");
    System.out.println("falling");
}
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
Atul Dureja
  • 27
  • 10
  • Have a look at [Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) and [How to use Swing Timers](http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html) and [for example](http://stackoverflow.com/questions/13022754/java-bouncing-ball/13022788#13022788) – MadProgrammer Jan 12 '16 at 19:57

3 Answers3

0

Your sleep() call happens inside your keyPressed() handler which is called by the Event Dispatch Thread (EDT). Every GUI event has to be processed by that thread, so while your keyPressed() handler is sleeping, your application will not be able to handle any other event. It will seem to "lock up."

The normal way to animate something is to create a periodic timer task that repeatedly updates the state of your objects (i.e., moves the ball).

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
0

As the above answer says you are using sleep inside EDT. I would suggest a simple Swing Timer . You can define a Swing Timer with a time in milliseconds after which the code is executed.

ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
    //...Update Ball Here...
  }
};
Timer timer = new Timer(100 ,taskPerformer);
timer.start();

Above code will update balls location after every 100 ms.Use timer.stop() when ball reaches bottom.

0

You may have to update the balls x and y independently from the thread, so I suggest you create a class that handles all that for you

public class Ball {

    private int x;
    private int y;

    private int velY;
    private int velX;

    public Ball(int x, int y, int velY, int velX){
        this.x = x;
        this.y = y;
        this.velX = velX;
        this.velY = velY;
    }

    public void update(){
        //Call this each time you update (Say 60 times per second)
        //if (noFall) velY = 0;
        y = y + velY
        x = x + velX


        //Gravity Effect
        velY++;

    }

    public void draw(){
        //Draw code here
    }

}

This is what you kind of did, but instead of freezing the whole thing, you will be freezing the ball/falling at any given time

Make sure to look at all the comments, the if statement shows a boolean noFall, you will have to create this publicly in the class so you can freeze the falling.