我目前正在用 Java 制作 2D 回合制策略游戏。在开发的这个阶段,我正在测试不同种类的人工智能。
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();
}
我现在的问题源于这样一个事实:人工智能执行代码的速度比重新绘制的速度快。发生这种情况时,我开始在各种绘图函数中收到诸如 NullPointerException 和 ConcurrentModificationException 之类的错误,因为 gameLoop 内部的逻辑更改变量的速度比重绘发生的速度更快。如果我在 AI 调用 gameLoop 的频率上添加手动延迟或只有 2 个人玩,错误就会消失。
根据我对 Java 文档的研究和阅读,我了解到重绘会立即返回,并且所有图形调用都会放入 EventQueue 中,直到 Java 确定有足够的调用来保证实际的重绘。到目前为止,我能找到的唯一解决方案是将 gameLoop 中发生的逻辑代码放入匿名可运行类中,并使用 SwingUtilities.invokeAndWait 调用代码,但这对我来说不是一个有效的解决方案,因为这会导致实际的人类交互从点击到错误。我考虑过使用锁来为 gameLoop 的逻辑部分/重绘提供互斥(因此一次只能执行一个),但我不确定这在处理 Java 图形时是否是一种好的做法。
目前,我愿意接受任何关于如何缓解我的问题的建议。
谢谢。
最佳答案
我的建议是你应该使用 Swing 计时器
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();
}
这样做你就不会那么频繁地重画。希望有帮助!
关于java - 如何在 JPanel 中快速更新图形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22086827/