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

查看:24
本文介绍了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 来制作我的图形(也就是说,整个游戏都使用 Graphics2D 对象显示在 JPanel 上).到目前为止,我没有遇到任何问题.

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.

我的入口游戏循环在线程(不是 EDT)的 run() 方法内运行.所以我一直在修改 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 元素一样,操纵非 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++ 不同,在 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.

你能做的最好的事情是在 EDT 线程上设置你的 GUI,在不同的线程上运行你的游戏逻辑,每 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.

顺便说一句,您确定您最初的问题(时不时的长时间延迟,但并非总是如此)不是垃圾收集的结果吗?我已经看过好几次了;如果您不使用并行垃圾收集器,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天全站免登陆