What's the best way to update a screen every interval of time t for graphics? Assuming the update method is called with update(), and all actual graphics stuff takes place there and is already handled and everything.
I've used the javax.swing.Timer which triggers an action event ever specified interval of time to run my update methods in the past, however the speed of the computer is still a factor. So if I'm doing it the best way (which I doubt) how do I leave updating exclusive to time?
The system clock calls in Java aren't necessarily super accurate. Here's one way to take into account update time when waiting for a specified period.
In this example, we're updating every 40 milliseconds, or 25 frames a second.
package com.ggl.testing;
public class TimerRunnable implements Runnable {
private static final long interval = 40L; // 40 milliseconds
#Override
public void run() {
long startTime = System.currentTimeMillis();
while (true) {
update();
long endTime = System.currentTimeMillis();
long elapsedTime = endTime - startTime;
elapsedTime = Math.max((interval - elapsedTime), 5L);
sleep(elapsedTime);
startTime = System.currentTimeMillis();
}
}
private void sleep(long interval) {
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
}
}
private void update() {
}
}
We see how long it takes to perform the update method. We calculate the elapsed time, and make sure the interval minus the elapsed time doesn't fall below 5 milliseconds. if it takes longer than 35 milliseconds to do the update, we will drop the frame rate to keep up.
Related
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;
}
}
I am looking for the best way in Java to monitor the computer clock (the minutes) and to fire off a method/thread every time it changes.
So if the time is 13:20 and it changes to 13.21 then do something. So any time there is a minute change some code gets fired.
What is the best way to listen to the minute section of the clock for changes ?
Thanks,
Richard
Find the current system time using System.currentTimeMillis()
Calculate how many milliseconds until the next minute
Schedule a TimerTask on a Timer to run in that number of milliseconds in the future
In that TimerTask's event handler schedule a new reoccurring TimerTask to run every 60,000 milliseconds.
int milisInAMinute = 60000;
long time = System.currentTimeMillis();
Runnable update = new Runnable() {
public void run() {
// Do whatever you want to do when the minute changes
}
};
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
update.run();
}
}, time % milisInAMinute, milisInAMinute);
// This will update for the current minute, it will be updated again in at most one minute.
update.run();
Sounds like a job for Quartz. You can do this using the following cron expression:
0 * * * * ?
Date d = new Date(System.currentTimeMillis());
Then you can get the minutes by d.getMinutes(). Have a check running in a thread waiting for the value of d.getMinutes() to change.
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.
public static final long TIMEOUT = 60000;
public static final long SYSTEM_TIME = System.currentTimeMillis();
I have the TIMEOUT Value for my application set as 60000 and i have my system time. Now how would i know that 50 seconds has been elapsed and i need to show a message to the end-user.
if (TIMEOUT - SYSTEM_TIME <= 10000) {
Toast.makeText(getApplicationContext(), "10 Seconds Left", Toast.LENGTH_LONG).show();
disconnectHandler.postDelayed(disconnectCallback, DISCONNECT_TIMEOUT);
}
If you don't need to do other stuff in that thread you can use a sleep(50000).
This is how to run a specific task one-shot:
new Timer().schedule(new TimerTask() {
#Override
public void run() {
// TODO
...
}
}, TIMEOUT);
The doc is here (as reported by jimpanzer)
Maybe that you can use something like this :
long startTime = SystemClock.elapsedRealtime();
// do what you want
long endTime = SystemClock.elapsedRealtime();
long ellapsedTime = endTime - startTime;
if (ellapsedTime>TIME_OUT) {
// do stuff
}
Maybe I am wrong or just not had enough coffee yet, but Timeout is 60000, your System value is much more - all millis starting at the year 1970 (if I am not mistaken here as well). This means your result from TIMEOUT - SYSTEM_TIME is negative and therefor a negative number and therefor smaller than 10000. So your if-statement always runs.
I am looking for the best way in Java to monitor the computer clock (the minutes) and to fire off a method/thread every time it changes.
So if the time is 13:20 and it changes to 13.21 then do something. So any time there is a minute change some code gets fired.
What is the best way to listen to the minute section of the clock for changes ?
Thanks,
Richard
Find the current system time using System.currentTimeMillis()
Calculate how many milliseconds until the next minute
Schedule a TimerTask on a Timer to run in that number of milliseconds in the future
In that TimerTask's event handler schedule a new reoccurring TimerTask to run every 60,000 milliseconds.
int milisInAMinute = 60000;
long time = System.currentTimeMillis();
Runnable update = new Runnable() {
public void run() {
// Do whatever you want to do when the minute changes
}
};
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
update.run();
}
}, time % milisInAMinute, milisInAMinute);
// This will update for the current minute, it will be updated again in at most one minute.
update.run();
Sounds like a job for Quartz. You can do this using the following cron expression:
0 * * * * ?
Date d = new Date(System.currentTimeMillis());
Then you can get the minutes by d.getMinutes(). Have a check running in a thread waiting for the value of d.getMinutes() to change.