Pausing a game loop? - java

So I have this piece of code, setting dt in a game loop (clock is of type Clock):
// set delta time
float currentTime = clock.getElapsedTime().asSeconds();
float dt = currentTime - lastTime;
// ...
lastTime = currentTime;
However, when the game is paused, the clock still runs. So as the game is paused, dt becomes large. How would I avoid this?

A possible, basilar approach could be something like the following one (pseudocode):
var elapsed = current - previous;
if(elapsed > clampOverElapsed) {
elapsed = clampOverElapsed;
}
Where clampOverElapsed is set somewhere to a reasonable value, as an example 25 ms.
This way, by having that control within the loop, you should nicely handle pauses as well as unseasonably longer iterations, without caring about what's the source of your big elapsed value, so that you have not to explicit

Related

System.nanotime return wildly different times

So i'm trying to implement a sort of day-night cycle in my game, and I'm using System.nanotime() to get the approximate time passed between frames, the problem is that it sometimes jumps huge amounts of time
Using lwjgl, and calling Timer.update() before swapBuffers with vsync enabled should be around 16.6ms increase to the current time each loop shouldnt it? Yet it can be much much higher than that with no actual slowdown for rendering
Here's the code : Time class
public class Time
{
public static final long SECOND = 1000000000L;
private static long lastTime;
public static long getTime()
{
return System.nanoTime();
}
public static double getDelta()
{
return (double)(getTime() - lastTime) / SECOND;
}
public static void update()
{
Time.lastTime = Time.getTime();
}
}
Update method
while ( !glfwWindowShouldClose(window) )
{
input();
update();
render();
}
public void update()
{
//System.out.println("Time since last update " + Time.getDelta());
Time.update();
}
And where i'm using the delta time :
if ((timeOfDay + Time.getDelta()) < timeDayTotal)
timeOfDay += Time.getDelta();
else
timeOfDay += Time.getDelta() - timeDayTotal;
System.out.println("Time of day " + timeOfDay);
Ignoring the fact that the precision seems to be waaaay off for now, here's some sample output
Time of day 0.0077873133
Time of day 0.0077988105
Time of day 0.0078120963
Time of day 0.007860638
Time of day 0.015185255
Time of day 0.01879608
Time of day 0.01880809
Time of day 0.018820863
Time of day 0.018835938
Time of day 0.018851267
It seems to mostly increment the correct amount (by a factor of 10^-4, but close enough, thats not the problem), but then it has these massive jumps up that I can't explain
So finally, a) whats the problem with system.nanoTime and b) is there a fix or viable replacement?
Edit : Switched to currentTimeMillis(), the precision is gone which is no big deal, but the jumps are still there
Time of day 0.03
Time of day 0.03
Time of day 0.03
Time of day 0.03
Time of day 0.06
Time of day 0.06
Time of day 0.06
Time of day 0.06
In general, do not use System.nanoTime() in any program which you don’t plan to strongly control how it is run, and the environment it is run in.
..
The problem lies in the RDTSC instruction which retrieves the number of CPU ticks since the CPU started. On multi-core systems, each core will have its own tick count, and they will not match, so every time your process switches CPUs, you get a different measurement. The issue is compounded by the fact that some power management systems actually alter the CPU’s frequency to save power, which breaks the functionality even on single core, single CPU systems.
From here
From the code you posted, it looks like you update() the Time on each frame before rendering, so then when you use getDelta() you only measure the time it took to get there, rather than the whole frame time?
I think it should look more like this:
public class Time
{
public static final long SECOND = 1000000000L;
public static final double timeDayTotal = 100.0; // ?
private static final long start = System.nanoTime();
private static double timeOfDay;
public static void update() {
long now = System.nanoTime();
timeOfDay = (now - start) / (double)SECOND % timeDayTotal;
}
public static double getTimeOfDay()
{
return timeOfDay;
}
}

Why would the same code be shorter inside a for loop?

So I've written a rather silly program just to work with nanoTime a bit. I wanted to be able to check execution times of small bits of code so I figure nanoTime would be the best. I wanted to determine the average execution time of this short bit of code, so I put it inside a for loop. However, when inside the for loop, the average drops to about 6,000 nano seconds less. I know this isn't a huge difference on small code but I am curious why it would be any different for the same exact code?
here are the two blocks that yield different times:
this one is an average of about 8064 nano seconds:
long start, end, totalTime;
double milliseconds, seconds, minutes, hours, days, years;
totalTime = 0;
start = System.nanoTime();
milliseconds = System.currentTimeMillis();
seconds = milliseconds/1000;
minutes = seconds/60;
hours = minutes/60;
days = hours/24;
years = days/365;
end = System.nanoTime();
totalTime = end-start;
and this one is an average of about 2200 nano seconds:
long start, end, totalTime;
double milliseconds, seconds, minutes, hours, days, years;
totalTime = 0;
for(int i = 1; i < 11; i++){
start = System.nanoTime();
milliseconds = System.currentTimeMillis();
seconds = milliseconds/1000;
minutes = seconds/60;
hours = minutes/60;
days = hours/24;
years = days/365;
end = System.nanoTime();
totalTime += end-start;
System.out.println(end-start); //this was added to manually calc. the average to
//make sure the code was executing properly. does not effect execution time.
}
and then to find the average you take totalTime*.1
This is exactly what you should expect from any Java program. The Java runtime, specifically the JIT compiler, will optimize code more heavily the more it gets run over the lifetime of the program. You should expect code to speed up after getting run multiple times.

How to represent passing of time?

I'm creating a simple simulation of gas station as homework. The total duration of the simulation is the week. Filling cars is approximately 3 minutes depending on the type of fuel. Cars may be collected in a queue. Now the question. I know how to implement these methods, but have no idea how to simulate a period of time without methods like a Thread.sleep().
P.S. I'm using JavaFX framework for this task. Cars are represented as javafx.scene.shape.Rectangle and their movements through Tranlsate methods. Dispensers too.
The Thread.sleep() method accepts a millisecond value. Basically, you can run an update and then calculate how long you need to sleep until the next update.
You can measure real time elapsed with System.nanoTime(). Make sure your class implements Runnable. Inside the run method, stick a while loop which contains an update() method to update the cars. Get nano time at the start and end of the loop, subtracting the two which gives you elapsed time. Subtract the elapsed time from the time you want each update to take, then sleep the thread. I think that is really all you need.
Here is the code:
public void run() {
int updatesPerSecond = 5;
/* The target time is the time each update should take.
* You want the target time to be in milliseconds.
* so 5 updates a second is 1000/5 milliseconds. */
int targetTime = 1000 / updatesPerSecond;
long currentTime;
long lastTime = System.nanoTime();
long elapsedTime;
long sleepTime;
while (running) {
// get current time (in nanoseconds)
currentTime = System.nanoTime();
// get time elapsed since last update
elapsedTime = currentTime - lastTime;
lastTime = currentTime;
// run your update
update();
// compute the thread sleep time in milliseconds.
// elapsed time is converted to milliseconds.
sleepTime = targetTime - (elapsedTime / 1000000000);
// don't let sleepTime drop below 0
if (sleepTime < 0) {
sleepTime = 1;
}
// attempt to sleep
try {
Thread.sleep(sleepTime);
} catch(Exception e) {
e.printStackTrace();
}
}
}
Within JavaFX framework,
you can simply use PauseTransition to simulate periodic time elapsing. On end of every period update scene graph elements' states. If you are going to change some properties of some node and do various animations you may utilize other types of Transitions. For more fine grained control you can use Timeline with its KeyFrames.

I cant count time period

I have code which checks if the given "A" time (in milliseconds) is in the given "b" time period.
private static boolean isInTimeInterval(long time, int timePeriod) {
long curTime = Calendar.getInstance().getTimeInMillis();
// time period is in hours, 1 hour is 3600000 ms;
long startTime = curTime - timePeriod * 3600000;
if (time >= startTime && time < curTime){
return true;
}
return false;
}
I take the time from a file and parse it into a long like this:
(Long.parseLong(array[2]))
But it doesn't work correctly, what is wrong ?
To simplify things, I would suggest that you first subtract the start time from the end time, check to see if that is positive and then decide if the remaining milliseconds is smaller than the requested time period.
long difference = Calendar.getInstance().getTimeInMillis() - time;
long timeRange = timePeriod * 3600000;
return (0 <= difference && differance <= timeRange);
It makes the code slightly smaller in lines, but more importantly, it simplifies the math to where you know the code isn't the problem.
As far as the errors you are likely encountering, I'd look to your
Long.parseLong(array[2])
As that is likely grabbing the input in a manner you aren't expecting. For starters, I'd put in some logging or at least one-time println debugging statements to verify the input times are what I thought they were.

How to print time elapsed (seconds) java

in my run method of a game loop I tried to print the time the program has been running in java. I simply tried System.out.println(System.nanoTime() / 1000000); because that's how many milliseconds are in a second.(if you didn't know) It prints the seconds near the end but I wanted exact seconds for testing purposes. I searched online and someone suggested using the same formula I thought of. Can anyone give an exact one?
Store previous time in a private member.
private long previousTime;
Initialize it in the constructor.
previousTime = System.currentTimeMillis();
Compare it with current time in run method (each iteration of game loop)
long currentTime = System.currentTimeMillis();
double elapsedTime = (currentTime - previousTime) / 1000.0;
System.out.println("Time in seconds : " + elapsedTime);
previousTime = currentTime;
In addition to the other answers provided, you could use a standard library StopWatch, like the one provided by Google's Guava API:
Stopwatch stopwatch = new Stopwatch();
stopwatch.start();
calculate();
stopwatch.stop(); // optional
long Seconds= stopwatch.elapsedMillis() / 1000000; // equals 1 second
You can use System.currentTimeMillis to get the current time in milliseconds.
If you pick this value at the start of your application and at the end, the subtraction of both values will give you the time your application was running.
final long start = System.currentTimeMillis();
// your code here...
final long end = System.currentTimeMillis();
System.out.println("The program was running: " + (end-start) + "ms.");
If you want it in seconds, just divide it with 1000 like you mentioned.
System.out.println("The program was running: " + ((double)(end-start)/1000.0d) + "ms.");

Categories