拖动窗口时不会调用Libgdx暂停/恢复(Windows)

我正在用libgdx创build一个Java游戏。 真的喜欢引擎到目前为止,但我注意到拖动游戏窗口时的问题。 渲染似乎停止(这是好的),但我无法find任何事件,在这种状态期间被调用。 有什么办法可以把它陷害吗? 当我限制deltaTime时,渲染并不是什么大问题,但是对于input来说,keyUp事件不会被激发,从而弄乱了播放器的移动代码(如果要在拖动窗口时释放按键)。 有什么我可以做的吗? 谢谢!

您描述的问题在于LWJGL 显示器的本地窗口实现:这个轻量级窗口在移动时不会松动焦点。 所以打电话

 Display.isActive() 

虽然移动窗口仍然会返回true,即使显示不再更新。

我找到了解决这个问题的一个解决方法,适用于我自己的项目。 可以通过调用将父画布添加到LWJGL显示中

 Display.setParent(canvas); 

通过这种方法,人们可以通过监听父类来监听窗口事件。 将父画布添加到显示器也是LwjglApplet所做的,所以可以在小应用程序内部运行libgdx应用程序。

我写了一个LwjglFrame类,它基本上遵循与LwjglApplet相同的方法,不同之处在于画布被添加到JFrame中:

 import java.awt.BorderLayout; import java.awt.Canvas; import java.awt.Dimension; import javax.swing.JFrame; import com.badlogic.gdx.Applicationlistner; import com.badlogic.gdx.backends.lwjgl.LwjglApplication; import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; public class LwjglFrame extends JFrame{ private final Canvas canvas; private LwjglApplication app; public LwjglFrame(final Applicationlistner listener, final LwjglApplicationConfiguration config) { canvas = new Canvas(){ public final void addNotify () { super.addNotify(); app = new LwjglApplication(listener, config, canvas); } public final void removeNotify () { app.stop(); super.removeNotify(); } }; canvas.setIgnoreRepaint(true); canvas.setFocusable(true); setLayout(new BorderLayout()); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); add(canvas, BorderLayout.CENTER); setPreferredSize(new Dimension(config.width, config.height)); pack(); } public LwjglFrame(final Applicationlistner listener, final boolean useGL2) { canvas = new Canvas(){ public final void addNotify () { super.addNotify(); app = new LwjglApplication(listener, useGL2, canvas); } public final void removeNotify () { app.stop(); super.removeNotify(); } }; canvas.setIgnoreRepaint(true); canvas.setFocusable(true); setLayout(new BorderLayout()); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); add(canvas, BorderLayout.CENTER); } } 

有了这个类,就可以在JFrame中运行libgdx,然后监听ComponentEvents。 下面是一些示例代码,介绍如何创建一个LwjglFrame并暂停游戏,每当框架移动时:

 public static void main(String[] args) { // create the config as usual final LwjglApplicationConfiguration cfg = createConfig(); // create your Applicationlistner as usual final Applicationlistner application = createApplication(); // create an LwjglFrame with your configuration and the listener final LwjglFrame frame = new LwjglFrame(application, cfg); // add a component listener for when the frame gets moved frame.addComponentlistner(new ComponentAdapter() { @Override public void componentMoved(ComponentEvent e) { // somehow pause your game here MyGame.getInstance().pauseGame(); } }); // set the frame visible frame.setVisible(true); } 

这种方法的缺点是,需要一些专门的暂停状态,一旦窗口被移动就进入。 这个暂停状态必须由用户手动退出才能继续游戏。 好处在于,即使不停止游戏,屏幕至少会更新,而移动窗口(除了使用lwjgl本地帧以外)。

我还没有找到一个可靠的方法,只有在窗口移动期间暂停游戏,一旦移动完成后自动继续循环。 这里的问题是,JFrame没有发送开/关事件来移动框架,而是在窗口移动时不断通知移动事件。

编辑

你也可以让你的com.badlogic.gdx.Game实现Componentlistner:

 public class MayGame extends Game implements Componentlistner{ public void componentResized(ComponentEvent e) {} public void componentMoved(ComponentEvent e) { System.out.println("Window moved!"); // pause the game somehow } public void componentShown(ComponentEvent e) {} public void componentHidden(ComponentEvent e) {} } 

然后你创建你的游戏是这样的:

 public static void main(String[] args) { // create the config as usual final LwjglApplicationConfiguration cfg = createConfig(); // create your Game final game MyGame = new MyGame(); // create an LwjglFrame with your game and the configuration final LwjglFrame frame = new LwjglFrame(game, cfg); // add the game as a component listener frame.addComponentlistner(game); // set the frame visible frame.setVisible(true); }