拖动窗口时未调用Libgdx暂停/恢复(Windows) [英] Libgdx pause/resume not called when window is being dragged (Windows)

查看:76
本文介绍了拖动窗口时未调用Libgdx暂停/恢复(Windows)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用libgdx创建一个Java游戏.到目前为止,我确实很喜欢引擎,但是在拖动游戏窗口时我注意到了一个问题.渲染似乎停止了(没关系),但是我找不到在此状态下调用的任何事件.有什么办法可以把它困住吗?当我为deltaTime设置上限时,渲染并不是什么大问题,但是对于输入而言,不会触发keyUp事件,这会扰乱我为播放器提供的移动代码(如果要在拖动窗口的同时释放键).有什么我可以做的吗?谢谢!

I am creating a Java game with libgdx. Really liking the engine so far but I noticed an issue when dragging the game window. Rendering seems to stop (which is okay) but I cant find any events that get called during this state. Is there any way I can trap it? It not a big deal for rendering as I cap the deltaTime, but for input the keyUp events don't get fired which messes up my movement code for the player (if you are to release the keys while dragging the window). Is there anything I can do? Thanks!

推荐答案

您描述的问题在于LWJGL的本机窗口实现

The problem you describe lies in the native window implementation of the LWJGL Display: This lightweight window does not loose focus while it is being moved around. Therefore calling

Display.isActive()

在移动窗口时,即使不再更新显示,仍将返回true.

while moving the window around will still return true, even though the display is no longer updated.

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

I have found a workaround for this problem that works for my own project. One can add a parent Canvas to the LWJGL Display by calling

Display.setParent(canvas);

使用这种方法,可以通过侦听父类来侦听窗口事件.

With this approach one is able to listen to window events by listening to the parent class. Adding a parent canvas to the display is also, what LwjglApplet does, so one is able to run libgdx applications inside an applet.

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

I have written an LwjglFrame class, that does essentially follow the same approach as LwjglApplet, with the difference, that the canvas is added to a 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并暂停游戏:

With this class, one is able to run libgdx inside a JFrame and then listen for ComponentEvents. Here is some example code for how to create an LwjglFrame and pause the game, whenever the frame is moved around:

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本机框架时),屏幕至少也将得到更新.

The downside of this approach is, that one needs some dedicated pause state, that gets entered once the window is moved. This pause state must then be manually exited by the user to continue the game. The upside is, that even if one does not pause the game, the screen will at least get updated, while one is moving the window (other than when using the lwjgl native frame).

我还没有找到一种可靠的方法,仅在窗口移动期间暂停游戏,并在移动完成后自动继续循环.这里的问题是,JFrame没有发送用于移动框架的开/关事件,而是在窗口四处移动时不断地通知移动事件.

I have not yet found a reliable way, to pause the game only during movements of the window, and automatically continue the loop once the movement is finished. The problem here is, that JFrame is not sending on/off events for moving the frame, but instead continuously notifies movement events while a window gets moved around.

编辑

您还可以使com.badlogic.gdx.Game实现ComponentListener:

You could also make your com.badlogic.gdx.Game implement 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) {}

}

然后您像这样创建游戏:

Then you create your Game like this:

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);

}

这篇关于拖动窗口时未调用Libgdx暂停/恢复(Windows)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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