移动鼠标时 JPanel FPS 下降

JPanel FPS drops when moving mouse

我正在 Java 中使用 Swing JPanel 的扩展作为我的绘图表面制作一个小游戏。

我在面板的 paintComponent()

中绘制所有内容

游戏运行流畅,直到我开始移动鼠标。当我这样做时,我会得到巨大的 FPS 下降,特别是如果我移动得非常快,使游戏无法玩。 即使我停止绘制鼠标光标也会发生这种情况。

JComponent 个对象上绘图时,这正常吗?

P.S。我在我的任何组件上都找不到任何已注册的 MouseListenerMouseMotionListener 对象。


编辑:

MCVE

import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;

public class AnimationSlowDownOnMouse {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        JFrame mainWindow = new JFrame("dotShoot");
        mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainWindow.setExtendedState(JFrame.MAXIMIZED_BOTH);

        final GamePanel gp = new GamePanel();
        gp.setPreferredSize(new Dimension(1920, 1080));
        mainWindow.add(gp);

        mainWindow.pack();
        gp.init();

        Thread gameThread = new Thread(new Runnable() {
            @Override
            public void run() {
                final int maxTicksPerSecond = 100;
                final int optimalTimePerTick = 1000 / maxTicksPerSecond;

                final int maxFrameSkips = 5;

                long tickCount = 0L;
                float AvgIES = 0f;
                //int FPS = 0;          
                int DCPS = 0;
                int TPS = 0;
                long timeStarted = System.currentTimeMillis();
                long timeElapsed = 0L;

                int tickReset = 0;
                int drawCallsReset = 0;
                long timeReset = timeStarted;
                float interpolationReset = 0f;

                long nextLoop = timeStarted;
                int frameSkips = 0;

                float interpolation;

                while (true) {
                    synchronized (this) {
                        frameSkips = 0;

                        while (System.currentTimeMillis() > nextLoop && frameSkips < maxFrameSkips) {
                            gp.update(tickCount);
                            nextLoop += optimalTimePerTick;
                            tickCount++;
                            tickReset++;
                            frameSkips++;
                        }

                        interpolation = (float) (System.currentTimeMillis() + optimalTimePerTick - nextLoop) / (float) optimalTimePerTick;
                        gp.setInterpolation(interpolation);
                        gp.repaint();
                        interpolationReset += interpolation;
                        drawCallsReset++;
                        timeElapsed = System.currentTimeMillis() - timeStarted;

                        if (System.currentTimeMillis() - timeReset >= 1000) {
                            AvgIES = interpolationReset / (float) drawCallsReset;
                            interpolationReset = 0f;

                            TPS = tickReset;
                            tickReset = 0;

                            DCPS = drawCallsReset;
                            drawCallsReset = 0;

                            timeReset = System.currentTimeMillis();
                        }
                    }
                }

            }
        });
        gameThread.start();

        mainWindow.setVisible(true);

        gp.requestFocus();
    }

}

class GamePanel extends JPanel {

    /**
     *
     */
    private static final long serialVersionUID = 3110478596996378903L;

    public GamePanel() {
        this.getInputMap().put(KeyStroke.getKeyStroke("pressed A"), "pressed Key");
        this.getInputMap().put(KeyStroke.getKeyStroke("released A"), "released Key");
        this.getInputMap().put(KeyStroke.getKeyStroke("pressed D"), "pressed Key");
        this.getInputMap().put(KeyStroke.getKeyStroke("released D"), "released Key");
        this.getInputMap().put(KeyStroke.getKeyStroke("pressed W"), "pressed Key");
        this.getInputMap().put(KeyStroke.getKeyStroke("released W"), "released Key");
        this.getInputMap().put(KeyStroke.getKeyStroke("pressed S"), "pressed Key");
        this.getInputMap().put(KeyStroke.getKeyStroke("released S"), "released Key");

        this.getActionMap().put("pressed Key", new AbstractAction() {
            private static final long serialVersionUID = 1296609706338138539L;

            @Override
            public void actionPerformed(ActionEvent arg0) {
                if (!pks.contains(arg0.getActionCommand())) {
                    pks += arg0.getActionCommand() + ", ";
                }
            }
        });

        this.getActionMap().put("released Key", new AbstractAction() {
            private static final long serialVersionUID = 4364732373538162119L;

            @Override
            public void actionPerformed(ActionEvent arg0) {
                pks = pks.replace(arg0.getActionCommand() + ", ", "");
            }
        });

        this.setBackground(new Color(0x6495ed));
    }

    public void init() {

    }

    private String pks = "";

    public void update(long currentTick) {

    }

    private float interpolation = 0;

    public void setInterpolation(float interpolation) {
        this.interpolation = interpolation;
    }

    private int frames = 0;
    private long timeForFPS = 0;
    private int ActualFPS = 0;

    public int getFPS() {
        return ActualFPS;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.setColor(Color.black);
        g.drawString("FPS: " + ActualFPS, 0, 10);
        frames++;
        if (System.currentTimeMillis() - timeForFPS >= 1000) {
            ActualFPS = frames;
            frames = 0;
            timeForFPS = System.currentTimeMillis();
        }
    }
}

编辑 2:

http://tinypic.com/r/9bkf4k/8
http://tinypic.com/r/345m24i/8

与其他评论一样,当我在我的计算机上尝试上面的代码时,FPS 没有问题。我还在只有一个处理器的虚拟机上尝试过。当鼠标快速移动时,FPS 仍然没有明显下降。虽然处理器总是显示 100% 使用率。你用其他电脑试过这个吗?我怀疑,您也不会在那里看到 FPS 问题。因此,问题可能出在您的计算机上,而不出在您的程序代码上。