Java:使用Swing编程游戏

我对游戏开发比较陌生。 我一直在开发游戏和学习游戏开发2-3个月。 我用的是Java。

我一直使用Swing作为我的图形(也就是说,整个游戏都显示在JPanel ,使用Graphics2D对象)。 到目前为止我对此没有任何麻烦。

最近,我在最近的项目中遇到了一个问题。 某些方法在以一致的时间间隔调用时存在问题(有时它会每15-16毫秒运行一次,因为它应该运行,有时它会开始每隔3000(!)毫秒运行一次)。

我做了一些令人沮丧的调试和一些研究,并发现发生这种情况的原因可能是因为我没有正确处理Swing和线程。

我的entrie游戏循环在线程的run()方法内run()不是EDT)。 所以我一直在修改EDT之外的Swing元素。 显然这必然会引起问题。

当我发现这是问题所在时,我想:

“嘿,我只是使用SwingUtilities.invokeLater()来运行EDT中的游戏循环!”

但后来我记得,就像在EDT 之外操纵Swing元素一样“被禁止”, 从EDT 内部操纵非Swing对象也是有问题我认为……这是正确的吗? )。

如果是这样,那么我不知道如何使用Swing在Java中开发游戏而不会遇到奇怪的问题

我的问题是:

如何使用Swing安全地开发游戏? 为了避免涉及Swing和线程的问题,对我来说要严格的准则是什么? 每个使用Swing的游戏开发者都应该知道吗?

这对我来说非常重要,因为我真的希望使用Java进行游戏开发,但如果我不理解这一点,我总会遇到奇怪的问题并且无法进展。

谢谢您的帮助

只要你不修改除面板上绘制的图形之外的任何东西,你应该在大多数时候都可以。 就像一个非EDT线程在大多数情况下一样 。 只要你不添加或删除任何gui元素,不要调整任何大小,不要隐藏任何东西等等,Swing不会在其内部细节上摆弄足以导致你的线程和EDT之间的竞争条件 – 大多数的时间。

即使用户在非EDT代码绘制时最小化面板的情况也不会导致崩溃 – 面板可能会丢弃其旧的图形上下文并开始使用新的图形上下文,但旧的上下文将保持有效直到你释放它(这与C ++不同,其中delete立即使对象失效,当另一个线程仍然使用本地指针时会导致崩溃)。

问题是如果你使用“我还没看到它出错的情况,总是为我工作”的方法,你依赖于未定义的行为,你的代码可能会在你更新后立即崩溃你的JVM。

你可以做的最好的事情是在EDT线程上设置你的GUI,在不同的线程上运行你的游戏逻辑,每隔20毫秒在面板上有一个定时器调用repaint() (或者你想要的帧速率)。 然后,有一个类对象,它包含显示当前游戏状态所需的所有内容。 在synchronized代码块中,让面板的paint()生成自己的对象副本,并让paint()使用副本,而主线程可以计算游戏需要的任何内容。 主线程当然应该使用相同的synchronized来写入类对象。 这样,您可以获得线程之间的最大可能间隔。

只是在EDT上运行你的整个游戏线程可能不会这样做,因为你的游戏可能需要一段时间才会导致UI冻结。 任何需要大量UI资源的东西都会影响你的游戏逻辑。

顺便说一句,你确定你的初始问题(时不时地长时间延迟,但并非总是如此)不是垃圾收集的结果吗? 我好几次见过这个; 如果您不使用并行垃圾收集器,GC可能会运行几十秒钟并阻止其他所有内容。