Rob
Rob

Reputation: 15992

Java : improve the smoothness of a slow thread animation?

I'm trying to create an animation like a hockey disc moving slowly and whose speed decreases little by little.

So I tried to do this :

for(Disc d : panel.getDiscs()
{
    if(d.getLaunch() <= 70) move(d);
}

And :

private void move(Disc d)
{
        Point p = d.getLocation();
        Point speed = d.getSpeed();
        Dimension size = d.getSize();

        int vx = speed.x;
        int vy = speed.y;

        int x = p.x;
        int y = p.y;

        if (x + vx < 0 || x + size.width + vx > panel.getWidth()) {
            vx *= -1;
        }
        if (y + vy < 0 || y + size.height + vy > panel.getHeight()) {
            vy *= -1;
        }
        x += vx;
        y += vy;

        d.setSpeed(new Point(vx, vy));
        d.setLocation(new Point(x, y));

    try
    {
        Thread.sleep(d.getLaunch());
    } catch (InterruptedException e)
    {
        e.printStackTrace();
    }
        if(d.getCoeff() < 5) d.setCoeff(d.getCoeff()+1);
        else { d.setLaunch(d.getLaunch()+1); d.setCoeff(0); }
}

What I'm trying to do here is to increase a value (launch) that begins at 20 and keeps running until 70, then I use this value in every Thread.sleep(launch);. I only increase this value when 5 frames were previously displayed (coeff).

The problem is the following : when I try it with a too small value, the disc is too fast and stops running too early. When I try it with a higher value, the disc speed looks well but the last animations are not very smooth... What should I do ?

Upvotes: 2

Views: 190

Answers (4)

fortran
fortran

Reputation: 76057

You should use the time delta to calculate the distance moved (remember: dx = v*dt) in each iteration so your animation speed is independent of the update rate.

Then you can use any other tips already mentioned (like a Timer) to make it more steady.

Upvotes: 1

Dariusz
Dariusz

Reputation: 22241

Your approach seems invalid. Displaying the disc and determining it's position are two different things. I think that:

  • in one thread you should periodically (100 times a second?) calculate the position of the disc
  • several times per second you should decrease the speed of the disc (base this speed decrease on System.currentTimeMIlliseconds(), not on how many times the loop was executed)
  • 30-60 times per second draw the position of the disc

Upvotes: 1

Marko Topolnik
Marko Topolnik

Reputation: 200158

What you should most definitely do, and which will improve the smoothness of your animation, is not use sleep as a way to pace the animation. This blocks the very thread that is in charge of painting the hockey puck. What you need is a SwingTimer that is appropriately scheduled to execute the animation. Give it a steady rate of firing and control the speed via the position delta that you apply.

Upvotes: 3

Oscar Gomez
Oscar Gomez

Reputation: 18488

I would recommend not using Thread.sleep at all, instead implement a gaming loop that gets called every so often by a timer, then simply slowly decrease the speed every loop.

Upvotes: 1

Related Questions