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.
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;
}
}
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.
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
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.");
I am making listview with timers, each with different deadline depending on the database(similar to auction)
Time now = new Time();
now.setToNow();
now.normalize(true);
nowMillis = now.toMillis(true);
.
.
String endtime = a.get(position).get(TAG_ENDTIME);
Integer timeSecond = Integer.parseInt(endtime.substring(17, 19));
Integer timeMinute = Integer.parseInt(endtime.substring(14, 16));
Integer timeHour = Integer.parseInt(endtime.substring(11, 13));
Integer timeDay = Integer.parseInt(endtime.substring(0, 2));
Integer timeMonth = Integer.parseInt(endtime.substring(3, 5)) - 1;
Integer timeYear = Integer.parseInt(endtime.substring(6, 10));
Time future = new Time();
future.set(timeSecond, timeMinute, timeHour, timeDay, timeMonth, timeYear);
future.normalize(true);
long futureMillis = future.toMillis(true);
long interval = futureMillis - nowMillis;
new CountDownTimer(interval,1000)
{
#Override
public void onTick(long millisUntilFinished)
{
Long interval = millisUntilFinished;
int days = (int) ((millisUntilFinished / 1000) / 86400);
int hours = (int) (((millisUntilFinished / 1000) - (days * 86400)) / 3600);
int minutes = (int) (((millisUntilFinished / 1000) - (days * 86400) - (hours * 3600)) / 60);
int seconds = (int) ((millisUntilFinished / 1000) % 60);
String countdown = String.format("%dd %dh %dm %ds", days, hours, minutes, seconds);
holder.duration.setText(countdown);
}
#Override
public void onFinish()
{
// TODO Auto-generated method stub
holder.duration.setText(TimeUp);
}
}.start();
That code works almost perfectly when there is only one instance.
However the problem arise when there is several instance, around 4-5 timer running at the same time
Several/all the countdown will start to flicker, be it seconds, minutes, hours, or days.
e.g. one of my timer flicker between 27d 11h 54m 50s and 0d 23h 47m 0s
Since this occur on both on emulator and on my device, it seems to be my code's flaw, but I don't have a clue what could cause this.
I tried to change
holder.duration.setText(countdown) into holder.duration.setText(millisUntilFinished)
and the the countdown flickers between the desired duration and a huge, random number,
Please help.
You should use one TimerTask and put all your UI updates into that single timer instead running multiple CountDownTimers for essentially the same job since you're already doing all the math to determine when "time is up" for any particular item, you might just run one TimerTask and once a second have it update everything. CountDownTimer is useful for a single implementation count down because it does some built-in math, etc. You're redoing all that math, so you might as well use one instance of a regular TimerTask.
The implementation of CountDownTimer relays on scheduled delays in Handler messaging. A single countdown instance is unlikely to result in any bizarre behavior, but if you have several going that all supposed to "tick" when the system clock hits each second (the time in millis ends in "000" - once a second, and all at the same time), then those handlers will all try to fire simultaneously and inevitably fail.
If the UI or other process will likely delay some of these messages, even to the point where it will "skip ticks" to catch up. Also, that means that the next message delay could be only milliseconds from the next tick (i.e. if it's supposed to check every 1000 millis, but is delayed an additional 1990 millis, then it will skip a tick and also schedule the next message for 10 millis into the future.