I'm making a small game in Java using an extension of Swing's JPanel
as my drawing surface.
I draw everything inside panel's paintComponent()
The game runs smoothly until I start moving my mouse. When I do I get huge FPS drops, especially if i move it very fast, making the game unplayable. That happens even when I stop drawing the mouse cursor.
Is this normal when drawing on JComponent
objects?
P.S. I couldn't find any registered MouseListener
or MouseMotionListener
objects on any of my components.
EDIT:
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();
}
}
}
EDIT 2:
http://tinypic.com/r/9bkf4k/8
http://tinypic.com/r/345m24i/8
As with the other comments, there is no problem with FPS when I tried the code above here in my computer. I also tried it on my virtual machine having one processor only. Still there is no dramatic drop of the FPS when the mouse is moving fast. Although the processor always shows 100% usage. Have you tried this with other computers? I suspect, you too won't see the FPS problem in there. So maybe the issue lies in your computer and not on your program code.