如何在JPanel中快速更新图形

时间:2014-02-28 05:16:25

标签: java swing graphics jpanel paint

我目前正在使用Java制作基于2D回合的策略游戏。在开发的这个阶段,我正在测试不同种类的AI。

AI通过将x和y变量发送到名为gameLoop的函数来与游戏进行交互,该函数通常由mouseClicked函数调用。这允许他们直接模拟人类用户,这使得他们更容易与游戏进行交互。以下是我的一些代码的概述:

paintComponent() {
    drawTiles();
    drawUnits();
    if(unitSelected && gameState == DISP_MOVE)
        drawMoveSpots();
}

gameLoop(int x, int y) {
    // various logic based
    // on the values of x and y
    // logic may set unitSelected to true or false
    // may also change gameState bteween normal and displayMoveSpots
    repaint();
}

我现在的问题源于这样一个事实,即AI正在执行代码而不是重绘。当发生这种情况时,我开始在我的各种绘图函数中得到诸如NullPointerException和ConcurrentModificationException之类的错误,因为gameLoop内部的逻辑正在以比重绘更快的速度更改变量。如果我在AI调用gameLoop或只有2个人玩的频率上添加手动延迟,则错误消失。

从我对Java文档的研究和阅读中,我了解到repaint立即返回,并且所有图形调用都被放到EventQueue上,直到Java确定有足够的调用来保证实际的重绘。到目前为止我能找到的唯一解决方案是将gameLoop中发生的逻辑代码放入一个匿名的runnable类中,并使用SwingUtilities.invokeAndWait调用代码,但这对我来说不是一个有效的解决方案,因为这会导致实际的人机交互从点击到错误。我已经考虑使用锁来为gameLoop的逻辑部分/重绘提供互斥(所以一次只能执行一次),但我不确定这是否是处理Java图形时的好习惯。

在这一点上,我愿意接受有关我可以采取哪些措施来缓解我的问题的建议。

感谢。

1 个答案:

答案 0 :(得分:1)

我的建议是你应该使用摇摆计时器

  import javax.swing.Timer;

  public static void main(String[] args) {
                             /*this is 1 sec/ 1000ms*/
    Timer aiTimer = new Timer(1000, new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            //move AI
            //repaint
        }
    });
    aiTimer.start();

}

通过这样做,你不会经常重画。希望有所帮助!