Best way to animate in Java?

2019-02-15 15:12发布

I'm currently using an animation engine I designed that takes objects of type Drawable and adds them to a List. Drawable is an interface that has one method:

public void draw(Graphics2D g2d);

The extending animation manager iterates through this list and calls the draw() method on every object, passing the Graphics2D object obtained from the Swing component.

This method seemed to work well at first, but as I feared, it seems to be unable to handle multiple objects in the long run.

With merely two Drawables registered, both drawing images on screen, I'm seeing a bit of flashing after 30-60 seconds.

Is there a way to optimize this method? It currently calls upon the AWT thread (invokeLater) to handle all of the tasks. Concurrent drawing isn't really an option as this nearly always causes issues in Swing/AWT, in large part due to the fact that Graphics isn't synchronized.

If this just simply is a bad way of animating, what is a better method when you have multiple objects that all need things rendered with their own specific variables cough game cough?

Any help would be appreciated. Thanks!

EDIT:

I can't use repaint() beacuse my engine already calls the AWT thread to paint stuff. If I call invokeLater from the AWT thread, the image never gets painted for some reason.

I should also add that I'm using a system of ticks and fps. 60 ticks @ 120 fps.

Each tick updates the game logic, while each frame render calls draw on the frame manager.

Is this a bad idea? Should I just use FPS and not ticks?

1条回答
\"骚年 ilove
2楼-- · 2019-02-15 15:53

I think it would be more appropriate to override paintComponent(Graphics g) and regularly call the repaint method on the JPanel or whatever you're drawing on with a Timer. Your problems may be due to to you trying to draw and then Swing doing it's own draw.

public class Main {
public static void main(String[] args) {
    JFrame frame = new JFrame();
    JPanel panel = new JPanel() {
        public void paintComponent(Graphics g) {
            //draw here
        }
    };
    panel.setPreferredSize(800, 600);
    frame.add(panel);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true)

    new Timer(16, new ActionListener() {
        public void actionPerformed(ActionEvent event) {
            panel.repaint();
        }
    }).start();
}
}
查看更多
登录 后发表回答