[SOLVED] About "Thread.sleep" on my main loop

Hi everyone!

I’m new here and finally I’ve decided to sign in because I found this is the best place to learn java gaming techniques!! I hope I can help others too…

Well, here’s my question:

I’m building a “mini-engine” for a tribute game to “Monty” (from the C64 versions of “Monty on the run” and “Auf wiedersehen Monty”), and recently I solved a problem I had with some tear effects or glitches (I don’t know how to call it…) in my animation code. Basically what happened was that in my computer everything went smooth but when I ran the tests on my laptop I noticed this issues. I’m using page flipping and in my “flip” method I had this:

public class MyGraphicsClass implements MyGraphicsInterface() {

… some methods here

public void flip() {
	//screen.dispose();	<-- doesn't work. once disposed it has to be retrieved again?
	strategy.getDrawGraphics().dispose();
	strategy.show();
	
	try {
		[b]Thread.sleep(10);[/b]
	} catch (Exception e) {}

}

}

Now, instead of sleeping for 10 ms I try to make the loop take exactly 10ms so I changed it to this:

	try {
		[b]Thread.sleep( game.getLastLoopMsecs() + 10 - HiresTimer.getTime() );[/b]
	} catch (Exception e) {}

Is this a good solution? Or is it better to keep a constant sleep time to let the OS “breathe” for a while? As I said, with a fix value is not so smooth in my laptop (Dell XPS)

Besides, I thought that as the game grows, every loop will take more time and the sleep time will be less and I don’t know if that’s ok or bad :slight_smile:

Btw, for now I’m using Sun’s Perf class in my HiresTimer (Eventually I’ll have to use another system I guess… but atm I’m interested in getting the basics done)

Oh, and another thing: I’m using UPS instead of FPS, should I change to FPS for better performance or is UPS ok?

Hi !
As Thread.sleep(10) is independent from computer’s performance, it is normal that there is a difference between two different computers. Instead you should do something like you do on the second example: get time before code execution, get time after and wait the appropriate among of time. This is the only way I know you can have a constant gameloop undependent from computer and size of code.
This is a way to do this (using FPS) (I hope there is no mistake :slight_smile: ).


double FPS = 60 (if you want 60 FPS)
double secondsPerTick = 1/FPS;

public void gameloop(){
        // Game loop
        previousTime = System.nanoTime();
        while (/* Not closing window */) {
			long currentTime = System.nanoTime();
			long passedTime = currentTime - previousTime;
			previousTime = currentTime;
			unprocessedSeconds += passedTime / 1000000000.0;
			
			while (unprocessedSeconds > secondsPerTick){
			    unprocessedSeconds -= secondsPerTick;
			    tickCount++;
			    if (tickCount % FPS == 0){
			    	System.out.println("FPS: " + frames);
			    	frames=0;
			    	previousTime+=1000;
			    }
			    // Execute code here
             do_code();
             frames++;
			}
		}
    }

For UPS, sorry but I’m not used to it…
The while process can be replace by a Thread.sleep (which is I think better)

Hey co_Opernicus and welcome to JGO!

What is this “screen” object? Graphics2D? What exactly “doesn’t work”? You’re supposed to dispose of it after you’re not done. Every time you call getDrawGraphics(), it gives you the Graphics2D object of another backbuffer, on that line “strategy.getDrawGraphics().dispose()”, you’re wasting a back buffer. Remove it!

As for sleeping, Thread.sleep is very inaccurate on Windows. You should use this sleeping method trick to make it more accurate. Put it at the beginning of your main method:


if(System.getProperty("os.name").startsWith("Win")) {
	new Thread() {
		{
			setDaemon(true);
			start();
		}
		
		public void run() {
			while(true) {
				try {
					Thread.sleep(Long.MAX_VALUE);
				}
				catch(Exception exc) {}
			}
		}
	};
}

As for sleeping, the best way to sleep is through a busy loop. Here is some sample code of my game loop:


public class MyGame implements Runnable {
    public static void main(String[] args) {
        new Thread(new MyGame()).start();
    }

    private final int WIDTH = 800, HEIGHT = 600;
    private final int FPS = 60;
    
    public void run() {
        JFrame frame = new JFrame("My game");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setIgnoreRepaint(true); //IMPORTANT, MUST INCLUDE!
        
        Canvas canvas = new Canvas();
        canvas.setPreferredSize(new Dimension(WIDTH,HEIGHT));
        canvas.setIgnoreRepaint(true); //IMPORTANT, MUST ALSO INCLUDE!
        frame.add(canvas);
        
        frame.pack();
        frame.setVisible(true);
        
        canvas.createBufferStrategy(2);
        
        BufferStrategy strategy = canvas.getBufferStrategy();

        long lastTime, lastFPS, frames = 0;
        lastTime = lastFPS = System.nanoTime();
        
        while(isRunning) {
            long deltaTime = System.nanoTime() - lastTime;
            lastTime += deltaTime;
            
            update(deltaTime);
            
            //Must setup these do-while loops like this according to BufferStrategy's Javadoc
            do{
                do{
                    Graphics2D g = (Graphics2D)strategy.getDrawGraphics();
                    
                    render(g);
                    
                    g.dispose();
                }while(strategy.contentsRestored());
                
                strategy.show();
            }while(strategy.contentsLost());
            
            //calculate the FPS
            frames++;
            if(System.nanoTime() - lastFPS >= 1e9) {
                System.out.println(frames);
                frames = 0;
                lastFPS += 1e9;
            }
            
            //Gets the remaining number of milliseconds left in the frame
            long sleepTime = Math.round((1e9/FPS - (System.nanoTime() - lastTime))/1e6);
            if(sleepTime <= 0)
                continue;
            
            //this sleeping method uses Thread.sleep(1) for the first 4/5 of the sleep loop, and Thread.yield() for the rest. This gives me an accuracy of about 3-4 microseconds
            long prev = System.nanoTime(), diff;
            while((diff = System.nanoTime() - prev) < sleepTime) {
                if(diff < sleepTime * 0.8)
                    try { Thread.sleep(1); } catch(Exception exc) {}
                else
                    Thread.yield();
            }
        }
    }
    
    public void update(long deltaTime) {
        //update logic
    }
    
    public void render(Graphics2D g) {
        //render your game
    }
}

Hi there! Thanks for your reply!

Sorry, my bad… that line was from an earlier version of the game, since this is the first time I’m using Java2D I didn’t understand well why I had to call “dispose” so I did some tests… But anyway, I still don’t get it. If I remove that line, when do I have to call dispose? Because now I’ve just commented it and everything works fine even if a don’t call it anywhere else o_O… Does it mean that “show” takes care of swapping buffers automatically?

For the rest, thanks a lot for the tips on sleeping!! I’ll try them

You’re disposing of the resources that Graphics2D uses. While it’s not absolutely necessary to dispose it, it wouldn’t hurt to add that line in.

And yes, show() takes care of swapping the buffers.

EDIT: Btw, take care to notice the double do-while loop pairs around the call to the render method. Those are necessary.

The problem with my “screen.dispose()” is that I initialized only once, when creating the instance, instead of doing it inside the loop as you do.


 do{
     do{
         Graphics2D g = (Graphics2D)strategy.getDrawGraphics();                
         render(g);
                    
         g.dispose();
     }while(strategy.contentsRestored());
                
  strategy.show();
  }while(strategy.contentsLost());

That’s why it didn’t work and I commented it… and that’s why I introduced “strategy.getDrawGraphics().dispose()” before doing strategy.show() without noticing that it has to be called before rendering. I’ll have to change some things in my design because right now my Graphics class is separated from the rendering and “strategy” is out of the scope of the rendering loop

Anyway, I think it’s time for some code refactoring… hehe

Again, thanks for your replies, they’re really helpful

Thanks Tim! I’ll check this when implementing the FPS control part

Concerning Tim’s FPS count, he only prints it when it reaches 60, therefore not actually calculating how many frames per second have been rendered.

Without any attempt t offend, I prefer ra4king’s code. I used like Tim’s one half year ago and yes, it worked. However that double loop while make better performance. Since then I’m following him :wink:

Sorry, you’re right ra4king, my FPS will always display 60 FPS :stuck_out_tongue:
I forgot to add do_code and frame++ again behind the while loop (then it should be better !)
But anyway, I’m sure ra4king proposition is better. I’ll take a look at it :wink: