Java 图形更新严重卡顿(简单的乒乓球游戏)

标签 java swing graphics paint repaint

我是更动态的 java swing 编程新手。当然,我之前也使用过常规的 swing 组件,包括 ButtonsPanels 等。

所以我尝试使用 SwingGraphics2D 制作一个非常基本的乒乓球游戏。我之前做了一个绘画程序,我成功了。

我的问题是程序运行时图形严重卡顿。到目前为止,我只实现了球,它只是选择一个随机方向并开始在面板中弹跳。这有效。但是,只有当我一直不断调整框架大小时,我才能看到球,否则它会严重卡顿,看起来是空白的。在第一秒左右,您实际上可以看到球在移动,但严重卡顿,然后面板开始显得空白。

相关代码和结构:

程序的主要部分是ControllerFrame类。其中 Controller 实现了 runnable 并包含一个执行游戏更新的 run 方法。

Frame 类扩展了 JFrame 并包含一个私有(private)实例变量 JPanel gamePanel,所有图形都在其中绘制。 JFrame 还有一个重写的 paint();方法

Controller更新程序时,它会调用Frame中名为updateGraphics()的类,该类之前调用​​paint(getGraphics( ));

public class Frame extends JFrame {

    private JPanel gamePanel;

    ....

    public void paint(Graphics g) {
        super.paint(g);

        label.setText(Integer.toString(ball.getPos().x) + ", " +  Integer.toString(ball.getPos().y));
        Graphics2D g2 = (Graphics2D) gamePanel.getGraphics();
        g2.setStroke(new BasicStroke(2));
        //g2.drawRect(0, 0, gamePanel.getWidth(), gamePanel.getHeight());

        try{
            //Draws the ball
            g2.fillOval(ball.getPos().x, ball.getPos().y, 10, 10);

            //Draws the player1(left) shield
            g2.setStroke(new BasicStroke(2));
            g2.drawLine(playerShield.getNorthX(), playerShield.getNorthY(), playerShield.getSouthX(), playerShield.getSouthY());
            g2.drawLine(playerShield.getNorthX(), playerShield.getNorthY(), playerShield.getSouthX(), playerShield.getSouthY());

            //Draws the computer/Player2(right) Shield
            g2.drawLine(computerShield.getNorthX(), computerShield.getNorthY(), computerShield.getSouthX(), computerShield.getSouthY());
            g2.drawLine(computerShield.getNorthX(), computerShield.getNorthY(), computerShield.getSouthX(), computerShield.getSouthY());
        } catch(Exception e) {
            System.out.println(e);
        }
    }

    ...

    public void updateGraphics() {
          paint(getGraphics());
    }

    //Another version of the updateGraphics i have tried to use with as little success

    public void updateGrapgics() {
         gamePanel.validate();
         gamePanel.repaint();
    }

}

在搜索时,我发现有人说我应该和不应该使用paint或repaint方法。

有人可以向我解释为什么它会口吃以及我应该如何做才能使其不口吃吗?

最佳答案

无需实现双缓冲或其他技巧。只需执行以下操作:

public class SomeVisualObject extends JComponent {
  public void paintComponent(Graphics g) {
    Graphics2D g2d = (Graphics2D)g;  
    // paint things
  }
}

...
final SomeVisualObject obj = new SomeVisualObject()
frame.add(obj);
...

final Timer repaintTimer = new Timer(20, new ActionListener() {
  public void actionPerformed(ActionEvent evt) {
    // do some stuff here, for example calculate game physics.
    // repaint actually does not repaint anything, but enqueues repaint request
    obj.repaint();
  }
});
repaintTimer.start();

并且它将顺利运行和绘制,没有任何故障。

只是不要弄乱循环。 Swing 运行它自己的事件循环,这对于重绘和其他内容至关重要。

在此处查看 2d 游戏对象(弹跳球)的完整且有效的示例:https://gist.github.com/akhikhl/8199472

关于Java 图形更新严重卡顿(简单的乒乓球游戏),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20858817/

相关文章:

c++ - 重绘分层窗口的正确方法

java - 使用 Objects#hash(Object...) 作为 hashCode 方法?

java - 从高度调整图像大小

java - 框架中未显示贝塞尔曲线

java swing不会显示

java - 将绘图从 R 流式传输到 Java,而不保存绘图

java - Spring:无法 Autowiring 字段 - 找不到类型的 bean

java - 在java中使用zip文件而不解压

java - 带有 JTextField 和 JButton 的 GridbagLayout,当 JButton 可见时重新格式化

java - 如何创建右侧包含用于在左侧显示的选项卡的 SplitPane?