I'm working on swing & graphic2D, And I ran into some issue, How to precise sleep?
Because for 144 or 240 fps monitor , ms is too long. With 4.1667ms Thread.sleep will cause very unstable result and time been scaled. Question is is there some way to real sleep under 1ms?
I did some research and found something like this Thread.Sleep for less than 1 millisecond
And according to the post, Event sleep(1) will not sleep accurate 1ms, As my test there is 100 times result:
551900
1932500
994600
939200
1903000
935000
958700
944200
938700
950800
953600
1920600
932500
954000
961700
1927400
930900
1936800
1913000
926500
1976200
957800
952000
940600
961000
971700
994800
1889500
1989800
907600
966100
1983600
1914300
1943300
999900
1911200
1988600
932500
1836100
1955500
913500
970200
956400
1902200
970300
1985300
1926100
990900
1804000
947700
1881400
933500
1963600
963000
928300
1913600
1016900
1824700
951600
1959900
938400
1951400
1957300
1965600
969400
1933800
936700
980000
961900
929500
1910000
936700
940100
976100
1975600
952100
986000
1959900
919300
1973500
1998700
1852000
931400
967500
1954200
2005800
1897200
968700
1925500
1945700
1917600
1946300
933200
957100
966400
944900
916000
934300
1887200
934200
None of them is close, At least will cause 10ms, And some of them even more then 20ms!
And 20ms is unacceptable for even 60FPS monitor. Because 16.67ms is the frame rate.
And I seek into Thread.sleep
public static void sleep(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis ;
}
sleep(millis);
}
I can't even believe java just treat nano second as ms if longer then 0.5ms, And other things like TimeUnit.sleep or Object.wait just call thread.sleep or convert into ms internal. So is that mean in windows or linux or any non-realtimeOS, There is no way to precise sleep? How game engine do that?
CodePudding user response:
Game engines relies on Delta time for making games frame rate independent, Delata time is nothing but elapsed time between the last frame and current frame. You can measure delta time as
DeltaTime = 1/FPS
So you can use this variable to make the game independent by multiplying this with your game variables, for example if you want to move a player independent of Frame rate you would do something like
Player.position = Player.position MovementSpeed * DeltaTime
If initial position = 10
, MovementSpeed = 1
If FPS = 60
, DeltaTime = 0.016666667
then distance after 1 second is
Player.position = 10 1 * (0.016666667*60)
which is '11'
(Here it's multiplied with 60 to simply acomodate the fact that same calculation will run for 60 times when game is running at 60 FPS so Player.position will be updated by 0.016666666 for 60 Times)
If FPS = 30
, DeltaTime = 0.03333
then distance moved after 1 seconds is
Player.position = 10 1*(0.03333*30)
which is '11'
So game can run independent of Frame Rates
You could try to calculate DeltaTime like:
//In main Game loop
current time = getSystemTime()
Delta time = current time - old time
old time = current time // save old time for next loop
CodePudding user response:
You need not sleep yourselvies. You should run your code as fast as possible. The monitor will help you synchronize your video output and you don't have to keep your code waiting for the monitor.
CodePudding user response:
Thread.sleep
has 2 methods, one of which accepts nanoseconds.
Thread.sleep(long millis, int nanos)
So Thread.sleep(1);
is equal to Thread.sleep(0,1000000);
So if you want to sleep half of a milisecond, use
Thread.sleep(0,500000)
Helpful Links:-
Add a decimal millisecond delay to Java code
Can a Thread sleep for less than half milli seconds in Java/ Other language?