Reputation: 125
EDIT: this bug only happens when I run my game on my Ubuntu 14.04 laptop. When I run it on the Windows school computers it works fine.
the window lags when running normally, but stops lagging while I resize the window with my mouse
I'm trying to make a simple game in java, however when ever I run it, it lags like crazy, I've looked over the code, and done some checks with System.out.println and System.currentTimeMillis and the code runs in much less than a millisecond, so that's not the problem.
The program stops when I drag to resize the window and constantly change the size of the window (presumably forcing a screen redraw), it has nice smooth animation when I do this.
When my program is running, it starts of with smooth animation, then about 1 second later it goes to about 2 FPS, then another second later to goes to 1 FPS, then about 0.5FPS and stays there until I force a repaint by resizing the window
my code is:
public class WindowSetup extends JPanel{
private static final long serialVersionUID = 6486212988269469205L;
static JFrame frame;
static JPanel panel;
protected void paintComponent(Graphics g){
super.paintComponent(g);
GameClass.draw(g);
}
public static void main(String[] args) {
frame = new JFrame("Evolver");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
panel = new WindowSetup();
frame.add(panel);
panel.setVisible(true);
frame.setVisible(true);
GameClass.init();
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
GameClass.tick();
panel.repaint();
}
};
Timer timer = new Timer(50,al); // lower numbers here make it run faster, but it still ends up slowing down to 1FPS
timer.start();
}
}
My GameClass:
public class GameClass {
static Random random;
static ArrayList<Enemy> enemies = new ArrayList<Enemy>();
static Wall wall;
static void init(){
random = new Random();
wall=new Wall();
for(int i=0;i<5;i++){
enemies.add(new Enemy(random.nextInt(200)+100,random.nextInt(200)+100,10,10,(float) (random.nextFloat()*(Math.PI*2)),1));
}
}
static void tick(){
for(Enemy d:enemies){
d.tick();
}
}
static void draw(Graphics g){
for(Enemy d:enemies){
d.draw(g);
}
wall.draw(g);
}
}
Enemy Class:
public class Enemy {
float x;
float y;
float width;
float height;
float direction;
float speed;
public Enemy(float x, float y, float width, float height, float direction, float speed) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.direction = direction;
this.speed = speed;
}
public void tick() {
direction += 0.01;
if (!(GameClass.wall.collides((int) (x + (Math.cos(direction) * speed)), (int) (y + (Math.sin(direction) * speed)),(int)width,(int)height))) {
x += Math.cos(direction) * speed;
y += Math.sin(direction) * speed;
}
}
public void draw(Graphics g) {
g.drawRect((int) x, (int) y, (int) width, (int) height);
}
}
Wall code:
public class Wall {
ArrayList<Rectangle> rectlist = new ArrayList<Rectangle>();
public Wall() {
// create list of walls here
rectlist.add(new Rectangle(10, 10, 50, 400));
rectlist.add(new Rectangle(410,10,50,400));
rectlist.add(new Rectangle(60,10,350,50));
rectlist.add(new Rectangle(60,360,350,50));
}
public void draw(Graphics g) {
for (Rectangle d : rectlist) {
g.drawRect(d.x, d.y, d.width, d.height);
}
}
public boolean collides(int x,int y,int width,int height){
for(Rectangle d:rectlist){
if(d.intersects(x, y, width, height)){
return true;
}
}
return false;
}
}
Upvotes: 1
Views: 1634
Reputation: 125
There's a problem with linux's graphics scheduling meaning it gets slower and slower for some reason. The solution to this is using Toolkit.getDefaultToolkit().sync() after you do panel.repaint(), this stops the slowdown.
This function doesn't seem to help anything on other OSes, but it does take up precious CPU cycles (quite a lot of them, actually), so use System.getProperty("os.name") to determine if you need to use it.
Upvotes: 6
Reputation: 399
As a workaround, I guess you can 'simulate' the resize behavior by adding setVisible(false)
and setVisible(true)
around your action listener:
public void actionPerformed(ActionEvent e) {
panel.setVisible(false);
GameClass.tick();
panel.repaint();
panel.setVisible(true);
}
Upvotes: 0