Heat Death
Heat Death

Reputation: 125

Java window lagging on Ubuntu but not windows when code isn't lagging

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

Answers (2)

Heat Death
Heat Death

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

javaguest
javaguest

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

Related Questions