当前位置: 首页 > 知识库问答 >
问题:

JavaFX KeyEvents使用robot.moveMouse()时延迟

解飞语
2023-03-14

我正在尝试在JavaFX中编写某种第一人称视角3D游戏,到目前为止,该运动效果非常好。

我使用JavaFX的内置shape和PerspectiveCamera类将图像渲染到场景中。

但是对于所有关键事件,输入延迟约为1-2秒。

滞后仅出现在:

>

  • 一旦程序切换到全屏(即使切换回窗口,它们仍然存在,但当程序刚刚启动时,它们仍然存在)

    并且在按下/释放按钮之前不久使用鼠标旋转相机

    例如:我按W前进,同时移动鼠标。如果我现在释放W,玩家仍然会向前移动1-2秒。如果不移动鼠标,就不会发生这种情况。

    这是跟踪输入的方式:

    scene.setOnKeyPressed(e -> keyPressed(e));
    scene.setOnKeyReleased(e -> keyReleased(e));
    

    和(对于密钥发布(e)它与“假”相同)

    private void keyPressed(KeyEvent e) {
        if (e.getCode().toString() == "W") w = true;
        if (e.getCode().toString() == "A") a = true;
        if (e.getCode().toString() == "S") s = true;
        if (e.getCode().toString() == "D") d = true;
    }
    

    对于相机移动,我使用此功能:

    private void mouseMovement(){
        if(primaryStage.isFocused()){
            mxdelta = MouseInfo.getPointerInfo().getLocation().getX() - centerx;
            mydelta = MouseInfo.getPointerInfo().getLocation().getY() - centery;
    
            // Rotate Camera
            cry += mxdelta * sens; // cry = camera rotation around y-axis
            crx -= mydelta * sens; // crx = camera rotation around x-axis
    
            // move curser back to the center of the screen
            robot.mouseMove(centerx, centery);
        }
    }
    

    如果我删除“robot . mousemove(centex,centey);”一切正常。同样,如果我通过箭头键控制摄像机的移动,也不会有延迟。

    整个游戏循环被打包在JavafX的AnimationTimer中,它提供了一个稳定的帧速率。

    另一个小观察:由于程序刚刚启动,有许多小口吃。一旦我切换到全屏,程序就会运行得非常流畅(当然,尽管输入滞后。但是鼠标根本没有输入滞后)。

    如果需要,我可以发布完整的代码,或者如果问题不够清晰,我可以上传视频。

  • 共有1个答案

    袁旻
    2023-03-14

    所以我发现,在另一个线程中运行整个主/游戏循环显然可以解决问题。不再有输入延迟,口吃也消失了。

    如果有人对我的解决方案感兴趣,这里是:

    首先,我将游戏循环中的所有内容打包到一个函数“mainloop()”中,它看起来大致如下:

    public void mainloop(){
        mouseMovement(); // <- full function is in the question above
        updatePosition();
        collisionDetection();
    }
    

    然后,我创建了一个新线程,只将主循环()放入其中:

    Thread t = new Thread() {
        public void run() {
            Platform.runLater(new Runnable() {
                public void run() {
                    mainloop();}
            });
        }
    };
    t.setDaemon(true);
    

    最后,使用AnimationTimer调用线程:

    new AnimationTimer() {
        @Override public void handle(long now) {
            t.run();
        }
    }.start();
    

    我不确定这是否是解决这个问题的有效方法,但它似乎很有效。

     类似资料:
    • 是否有关于何时使用任务的好规则。延迟对线程。睡觉 具体来说,是否存在一个最低值,以确保其中一个有效/高效 最后,自任务。延迟会导致异步/等待状态机上的上下文切换,使用它会有开销吗

    • 让事件延迟发生 用法: Your browser does not support the video tag. 案例:小台灯 功能:按下按钮,5s后灯亮,松开按钮,5s后灯灭 工作原理: 每一个输入都会在一段时间后(配置项中提供)被传送到输出。 当按钮被按下后,转动电机;一秒后再反转

    • 问题内容: 到底发生了什么 为什么我不能分配时间作为变量? 以及如何使用变量? 给定错误>>> 二进制运算符’+’不能应用于’DispatchTime’和’Float’类型的操作数 问题答案: 是一双。您不能将float和double值加在一起。 更换 与 它将正常工作。

    • 有时你可能想推迟调用一个方法;例如,在注册后的一天向新注册的用户发送电子邮件。要做到这一点,只需调用 BackgroundJob.Schedule 方法并传递所需的时间跨度: BackgroundJob.Schedule( () => Console.WriteLine("Hello, world"), TimeSpan.FromDays(1)); Hangfire Server

    • 问题内容: 我想在PyDev(Eclipse)python 2.75中创建一个图形窗口。 我做了几件事,但我想做一个“入口”“眨眼”。测试用户输入。如果是整数,则应闪烁绿色一秒钟,然后变为白色。但是,如果是其他字符串,则应闪烁红色,然后变成白色。我使用了a,但无法正常使用。 这是我执行此操作的代码: 问题答案: 阻止程序执行。 使用。 例如:

    • 我为我的草图创建了一个简单的延迟函数,并试图使用它,但似乎渲染停止了,也就是说,有一个简单的灰色屏幕,然后一切都被一次渲染。 有人能告诉我我在哪里吗出错了?到底发生了什么? 如何在内部定义绘制()和设置()?我知道,set()是一个一次性的渲染和绘制(),就像一个无限的循环。 代码: