Strange behavior of java game loop

196 Views Asked by At

I have a simple game loop in java:

public void run(){
    while(running){
        start = System.nanoTime();
        gamePanel.update();
        gamePanel.repaint();
        elapsed = System.nanoTime() - start;
        wait = (TARGET_TIME - elapsed) / 1000000;
        if(wait < 0){wait = TARGET_TIME;}
        try {Thread.sleep(wait);}catch(Exception e) {e.printStackTrace();}
    }
}

Now the problem: When i add a sysout in update() outing "updating" and one in paintComponent() outing "repainting", i get following result:

updating
updating
updating
updating
updating
(x1000 and more)
repainting

So when i repaint one time, the game is updating 1000 and more times. Is it normal? I think its abit strange, isnt it? For example can do 1000 steps with the player until the game is painting it... That means, the update() method doesnt wait for repaint finishing? Why?

Thank you!

Edit: Here the update code:

public void update(){
    if(moveUp){
        changeMapY(map, -map.getSpeed());
    }
    if(moveDown){
        changeMapY(map, map.getSpeed());
    }
    if(moveRight){
        changeMapX(map, map.getSpeed());
    }
    if(moveLeft){
        changeMapX(map, -map.getSpeed());
    }
}

Edit 2: And this is what changeMap does: (maybe this is the problem?)

public void changeMapX(Map map, int amount){
    for(int i = 0; i < blocks.length; i++){
        for(int j = 0; j < blocks[0].length; j++){
            blocks[i][j].addX(amount);
        }
    }
    map.addOffsetx(amount);
}

public void changeMapY(Map map, int amount){
    for(int i = 0; i < blocks.length; i++){
        for(int j = 0; j < blocks[0].length; j++){
            blocks[i][j].addY(amount);
        }
    }
    map.addOffsety(amount);
}
3

There are 3 best solutions below

7
On

You calculate wait in seconds. (nano-seconds / 1 million)

The parameter to sleep should be in miliseconds. So change this line:

wait = (TARGET_TIME - elapsed) / 1000;
0
On

I tested your source code and "updating", "repainting" are one after each other. The problem is connected with your update() method. Maybe recursion, maybe loop.

2
On

Assuming that gamePanel is a Swing component, what you're probably observing is that repaint() doesn't actually call JComponent.paintComponent(). All it does is essentially invalidates the component's graphics and tells Swing to repaint the component at a future point in time, on the Swing thread.

Multiple calls to repaint() don't necessarily result in multiple calls to paintComponent() - redundant repaint requests are collapsed into one.