Java:使用Swing编程游戏 [英] Java: Using Swing for programming games

查看:268
本文介绍了Java:使用Swing编程游戏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am relatively new to game development. I have been developing games and studying game development for 2-3 months now. I use Java.

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

I have always used Swing for my graphics (aka, the entire game is displayed on a JPanel, using a Graphics2D object). I had no trouble with this up until now.

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

Very recently, I came across a problem in my most recent project. Some method has problems with being called in consistent time intervals (sometimes it runs every 15-16 milliseconds, as it should, and sometimes it starts to run every 3000 (!) milliseconds).

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

I did some frustrating debugging and some research, and found out that the reason this happens is probably because I'm not handling Swing and threads right.

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

My entrie game loop runs inside the run() method of a thread (which is not the EDT). So I'm modifying Swing elements outside of the EDT all of the time. Obviously this was bound to cause problems.

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

When I found out this was the problem was, I thought:

嘿,我只需使用 SwingUtilities.invokeLater()就可以在EDT中运行游戏循环!

"Hey, I'll simply use SwingUtilities.invokeLater() in order to run the gameloop inside the EDT!"

但后来我记得,就像禁止强行操纵EDT 之外的 一样,操纵非Swing对象也存在问题来自里面 EDT 我认为......这是正确的吗?)。

But then I remembered, that just as it's 'forbidden' to manipulate Swing elements outside of the EDT, it's also problematic to manipulate non-Swing objects from inside the EDT (I think... is this correct?).

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

If so, then I have no idea how to develop games in Java using Swing without running into weird problems.

我的问题是:

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

这对我来说非常重要,因为我真的想用Java进行游戏开发,但如果我不明白这一点,我总会遇到奇怪的问题,无法继续前进。

This is very important for me to understand, since I really want to progress with game development using Java, but if I won't understand this, I'm always going to run into weird problems and won't be able to progress.

谢谢你的帮助

推荐答案

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

As long as you don't modify anything but the graphics drawn on the panel, you should be ok most of the time. Just like a single non-EDT thread works most of the time. As long as you don't add or remove any gui elements, don't resize anything, don't hide anything etc., Swing won't fiddle with its internal details enough to cause race conditions between your thread and the EDT - most of the time.

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

Even the case that the user minimizes the panel while your non-EDT-code is drawing on it will not cause crashes - the panel will probably throw away its old graphics context and start working with a new one, but the old context will remain valid until you release it (this is different from C++ where a delete invalidates the object immediately, which causes crashes when a different thread still uses a local pointer).

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

The problem is that if you're using the "i've yet to see a case where it goes wrong, always worked for me" approach, you're relying on undefined behaviour, and your code may start crashing as soon as you update your JVM.

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

The best thing you can do is set up your GUI on the EDT thread, run your game logic on a different thread, have a timer call repaint() on the panel every 20 ms (or whatever you want your frame rate to be). Then, have a class object that holds everything needed to display the current game state. Within a synchronized code block, let the panel's paint() generate its own copy of the object , and have paint() use the copy while the main thread calulates whatever the game needs. The main thread should use the same synchronized to write to the class object of course. That way, you get the maximum possible separation between the threads.

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

Just running your whole game thread on the EDT probably won't do, as anything your game does that might take a while will cause the UI to freeze. And anything that will need a lot of UI resources will affect your game logic.

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

BTW, are you sure your initial problem (long delays every now and then, but not always) isn't a result of garbage collection? I've seen this several times; if you aren't using the parallel garbage collector, GC might run for several 10's of a second and block everything else.

这篇关于Java:使用Swing编程游戏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆