Kyle Goertzen
Kyle Goertzen

Reputation: 143

How can I make a smooth animation in java instead of a stuttering

I'm making a game for practice and when I hit enter a knife pops up and I want it to look like its flying through air. Right now each time I click enter it skips about an inch and stops.

    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "onEnter");

    am.put("onEnter", new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            // Enter pressed
            throwKnife = true;
            if(move)
            {
                for(int i = 0; i < 10; i++)
                {
                    try
                    {
                        Thread.sleep(10);
                        knifeX += i;
                        repaint();
                    } catch (InterruptedException e1)
                    {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                }

                if(knifeX > 1200)
                {
                    throwKnife = false;
                    move = false;
                    knifeX = imageX+100;
                    knifeY = imageY+75;
                }
            }
            throwKnife = true;
        }
    });

This is paired with the following code in my paint component method

    if(throwKnife)
    {
        g.drawImage(knife, knifeX, knifeY, this);
        repaint();
        move = true;
    }

Upvotes: 0

Views: 587

Answers (2)

MadProgrammer
MadProgrammer

Reputation: 347334

Based on the use of the key bindings API and repaint, I'm guessing you're using Swing, in which case you're blocking the event dispatching thread with the Thread.sleep

See Concurrency in Swing for the reason why

Have a look at How to use Swing Timers for a simple solution

I should also point out that the ActionListener will be called repeatedly while the key is held down. A better solution would be to use a flag to indicate when the key is "active" and a "main loop" (like a Swing Timer) to update the state accordingly

Of course, this will require you to detect when the key is released, which can be achieved by binding the key again, but for release. See KeyStroke.getKeyStroke(int, int, boolean) for more details

For example, maybe have a look at

Upvotes: 1

DarkCygnus
DarkCygnus

Reputation: 7838

Right now each time I click enter it skips about an inch and stops.

I believe that in the part you wrote if(move){...} you actually wanted while(move){...}.

With the while clause you can have it move until it satisfies certain condition (like knifeX > 1200).

So, your code should look like this:

while(move)
{
    for(int i = 0; i < 10; i++)
    {
        try
        {
            Thread.sleep(10);
            knifeX += i;
            repaint();
        } catch (InterruptedException e1)
        {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }

    if(knifeX > 1200)
    {
        throwKnife = false;
        move = false;
        knifeX = imageX+100;
        knifeY = imageY+75;
    }
}

Hope it helps.

Upvotes: 0

Related Questions