何时在 2D 动画中对 SwingTimer 使用 Thread.sleep

When to use Thread.sleep over SwingTimer in 2D animation

本例中的上下文是创建一个与模型集成并每帧更新一次视图的游戏循环。监听器与控制器交互,控制器更新模型,repaint() 处理来自模型的视图更新(在 JPanel 上的重写 paintComponent())。

合适的回答有"never",哈哈。

这个问题我觉得有更好的答案,所以应该不违反规则。

我问这个是因为主游戏循环是一个 Runnable 实例,我锁定到 60FPS(目前大致如此。几毫秒的差异,因为当前的渲染循环非常便宜并且1000 / 60 每个周期损失一到两毫秒)。不通过 Thread.sleep() 锁定帧速率会导致大约每秒 2.3 亿 帧(显然),这可以理解地打击我的 CPU。不是问题,更多的是为什么需要帧锁定的例子。

然而,在我遇到的每一个答案、每一条评论中,大多数人都说 "why are you even touching Thread.sleep() you don't want the EDT to sleep"。如果您的循环中存在导致无响应的缺陷,这是可以理解的,但在我放在一起的应用程序中情况并非如此。我已经阅读了所有相关的事件调度线程文档,如何使用 Swing Timers 等。我什至自己也使用过 Timers 和 SwingWorkers(在一种情况下将图标加载委托给后台以防止 GUI 实例化时出现阻塞) .

这里有更好的方法吗?我在 Java 中没有遇到很多/任何不依赖于 libgdx 的独立游戏解决方案。

Thread.sleep 几乎肯定用于 javax.swing.Timer 和 java.util.Timer 的实现,但如今 Thread.sleep 的唯一实际用例是创建超时东西,通常是 I/O 连接。我曾在工作中使用过一次,用于在请求用户消息后延迟更新 GUI,直到从服务器发送的最后一条消息过去一段时间。我也用过here

在您的情况下,您应该在游戏循环中使用摆动计时器

在以下情况下使用 Swing Timer

您不想限制或控制更新之间的时间。 Swing Timer 仅保证“至少”持续时间(它将在给定的延迟后触发)并且处理事件的时间长度可能会影响下一次更新之前的时间量。

所以,如果你有 16 毫秒的延迟(大约 60fps),你的回调需要 20 毫秒来处理,第一次和第二次回调之间的时间实际上可能是 36 毫秒

当您想使用 Swing

提供的现有(被动)渲染系统时,您也可以使用 Swing Timer

Swing Timer 相对简单易用,它在事件调度线程中触发回调,可以轻松修改游戏状态并安排对 UI 的更新,这减少了可能的线程竞争条件(在绘画和更新之间)

在以下情况下使用 Thread#sleep

您希望更好地控制时间,从而产生可变延迟。为此,您需要管理自己的 Thread

这种方法更适合更复杂的动画以及当您使用 BufferStrategy 来控制输出时。

这样做的原因是,使用 Thread 方法,您 运行 线程更改状态和绘制循环绘制状态之间存在竞争条件的风险。相反,您将需要自己控制绘制过程,因此您知道在绘制某些东西时,状态不会在您进行时发生变化。

使用这种方法可以提供更大的灵活性和控制力来决定何时完成工作(以及如何完成),但会增加工作的复杂性和您的责任