我目前正在使用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图形时的好习惯。
在这一点上,我愿意接受有关我可以采取哪些措施来缓解我的问题的建议。
感谢。
答案 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();
}
通过这样做,你不会经常重画。希望有所帮助!