Investigation of optimal sleep time calculation in game loop

前端 未结 5 647
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-08 08:47

When programming animations and little games I\'ve come to know the incredible importance of Thread.sleep(n); I rely on this method to tell the operating system

5条回答
  •  北荒
    北荒 (楼主)
    2020-12-08 09:19

    You could use a cyclic timer associated with a mutex. This is IHMO the most efficient way of doing what you want. But then you should think about skipping frames in case the computer lags (You can do it with another nonblocking mutex in the timer code.)

    Edit: Some pseudo-code to clarify

    Timer code:

    While(true):
      if acquireIfPossible(mutexSkipRender):
        release(mutexSkipRender)
        release(mutexRender)
    

    Sleep code:

    acquire(mutexSkipRender)
    acquire(mutexRender)
    release(mutexSkipRender)
    

    Starting values:

    mutexSkipRender = 1
    mutexRender = 0
    

    Edit: corrected initialization values.

    The following code work pretty well on windows (loops at exactly 50fps with a precision to the millisecond)

    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    import java.util.concurrent.Semaphore;
    
    
    public class Main {
        public static void main(String[] args) throws InterruptedException {
            final Semaphore mutexRefresh = new Semaphore(0);
            final Semaphore mutexRefreshing = new Semaphore(1);
            int refresh = 0;
    
            Timer timRefresh = new Timer();
            timRefresh.scheduleAtFixedRate(new TimerTask() {
                @Override
                public void run() {
                    if(mutexRefreshing.tryAcquire()) {
                        mutexRefreshing.release();
                        mutexRefresh.release();
                    }
                }
            }, 0, 1000/50);
    
            // The timer is started and configured for 50fps
            Date startDate = new Date();
            while(true) { // Refreshing loop
                mutexRefresh.acquire();
                mutexRefreshing.acquire();
    
                // Refresh 
                refresh += 1;
    
                if(refresh % 50 == 0) {
                    Date endDate = new Date();
                    System.out.println(String.valueOf(50.0*1000/(endDate.getTime() - startDate.getTime())) + " fps.");
                    startDate = new Date();
                }
    
                mutexRefreshing.release();
            }
        }
    }
    

提交回复
热议问题