我正在使用libgdx创建Java游戏。到目前为止,我确实很喜欢引擎,但是在拖动游戏窗口时我注意到了一个问题。渲染似乎停止了(没关系),但是我找不到在此状态下调用的任何事件。有什么办法可以把它困住吗?当我为deltaTime设置上限时,渲染并不是什么大问题,但是对于输入而言,不会触发keyUp事件,这会扰乱我为播放器的移动代码(如果要在拖动窗口的同时释放键)。有什么我可以做的吗?谢谢!
您描述的问题在于LWJGL Display的本机窗口实现:此轻量级窗口在移动时不会失去焦点。因此打电话
Display.isActive()
即使不再更新显示,在移动窗口时仍将返回true。
我找到了适用于我自己的项目的解决此问题的方法。可以通过调用将父画布添加到LWJGL显示
Display.setParent(canvas);
通过这种方法,人们可以通过侦听父类来侦听窗口事件。LwjglApplet也会向显示添加一个父画布,因此可以在applet内运行libgdx应用程序。
我编写了一个LwjglFrame类,该类基本上遵循与LwjglApplet相同的方法,不同之处在于将画布添加到了JFrame中:
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Dimension;
import javax.swing.JFrame;
import com.badlogic.gdx.ApplicationListener;
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 ApplicationListener 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 ApplicationListener 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 ApplicationListener as usual
final ApplicationListener 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.addComponentListener(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实现ComponentListener:
public class MayGame extends Game implements ComponentListener{
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.addComponentListener(game);
// set the frame visible
frame.setVisible(true);
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句