From within my thread, I'm supposed to one thing every x seconds. Eg. let x=3, and it should do that thing at seconds 1, 4, 7, ... .
Making the thread wait() for x seconds wouldn't do-- because it may be interrupted for other thing(s) to do during this x second
period and thus can't keep track of the time passing in between the way it is supposed to.
So, the thread should come up with an efficient way of getting itself know that x seconds has passed on the clock.
What's the efficient way of doing that?
The only way I have now is keep checking the system clock to find out whether it's second 1, or 4, or 7, i.e. second i where i%3==1.
However, this is too wasteful and isn't any good.
What's the best way of doing this?
TIA.
//====================
EDIT:
I think it would me a method that looks up the system clock and interrupts me at every interval.
Does Java have a method like this somewhere?
I'm not sure what you're trying to do--something like this?
boolean interrupted;
long endWait = System.currentTimeMillis() + 3000; // or 1000 * x
do {
interrupted = false;
long timeRemaining = endWait - System.currentTimeMillis();
if (timeRemaining <= 0) {
break;
}
try {
Thread.sleep(timeRemaining);
} catch (InterruptedException e) {
... what you need to do when interrupted
interrupted = true;
}
} while (interrupted);
Related
I'm new to java and I'm trying to constantly add "zombie" entity to my game after a delay, and then shortening the delay as time goes on.
In my PlayState class I've got the code to spawn the entities in a position when my update(); method is run (which houses getInput(); and such. Not shown for clarity.)
public void update(long elapsed) {
this.entities.add(new Zombie(-535));
}
How would i make a delay that shortens? I'm guessing I would make the delay and then use a multiplier which i have getting smaller every 10 seconds or so, but how would I do this?
Now, I don't know much about the finer workings of your class, but this might give you a general idea of what I mean:
int counter = 50;
for(int i = 100; i >= 0; i--)
{
if(i == counter)
{
counter = counter / 2;
this.entities.add(new Zombie(-535));
}
}
Suppose i is the the total run-time of the game, and counter represents a percent of the game when you want to add a zombie.
If you want to add a zombie after 50% of the run-time (here, 100 seconds), then as the time reduces, you check if the time has come to add a zombie (Here, 50 seconds).
What I've done here is reduce the delay to half, and continue checking if the time has come to add a zombie.
Maybe you could call sleep on your thread of execution:
int sleepInMs = 5000
Thread.sleep(sleepInMs);
sleepInMs+=1000; //Then of course handle the case when sleepInMs == 0
Really need more information about your implementation.
For a simple delay, use "delay ms;"
Edit ms for the number of milliseconds you want. 1000 milliseconds is one second
I am writing some code to test using the MIDI libraries in Java, and have run across a problem. The pause between notes is much longer (almost twice as long, in fact) after the very first note than after all the others. I can't see any reason why, as the sequence of notes has already been generated (hence it is not also having to perform those calculations within the first iteration of the loop, it is only playing notes).
I think I may have also had this problem in the past with a simulation which, without any explanation I could find, took almost 100% of its tick length to perform calculations on the first tick only, and then used only about 2% on all successive iterations.
Main code (extract):
public void play() {
MidiPlayer player = new MidiPlayer();
for (int i = 0; i < NUMNOTES; i++) {
long tic = System.currentTimeMillis();
player.playNote(10, notes[i]);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
long toc = System.currentTimeMillis();
System.out.println(toc - tic);
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Code for playNote():
public void playNote(int channel, int note) {
channels[channel].allNotesOff();
channels[channel].noteOn(note + 60, volume);
}
There are no 'if' statements that specify the first loop, so surely the delay should be uniform for all notes, as the number of calculations being performed should be the same for all iterations. Please note that the timing variables are just for testing purposes, and the effect was audibly noticeable before I included those.
EDIT: I should also mention that the output produced shows each iteration of the loop taking the expected 200 (occasionally 201) milliseconds. It seems to suggest that there is no gap - yet I clearly hear a gap every time I run the code.
Since you have sleeps, you should calculate how long you should sleep instead of trying to sleep the same amount of time each time - calculate how much more time you actually need to the next note to be played and sleep that much amount. i.e.
long tic = System.currentTimeMillis();
player.playNote(10, notes[i]);
long time_spent = System.currentTimeMillis() - tic;
Thread.sleep(200 - time_spent);
I've written a class to continue a started JAVA application if the current second is a multiple of 5 (i.e. Calender.SECOND % 5 == 0)
The class code is presented below, what I'm curious about is, am I doing this the right way? It doesn't seem like an elegant solution, blocking the execution like this and getting the instance over and over.
public class Synchronizer{
private static Calendar c;
public static void timeInSync(){
do{
c = Calendar.getInstance();
}
while(c.get(Calendar.SECOND) % 5 != 0);
}
}
Synchronizer.timeInSync() is called in another class's constructor and an instance of that class is created at the start of the main method. Then the application runs forever with a TimerTask that's called every 5 seconds.
Is there a cleaner solution for synchronizing the time?
Update:
I think I did not clearly stated but what I'm looking for here is to synchronization with the system time without doing busy waiting.
So I need to be able to get
12:19:00
12:19:05
12:19:10
...
What you have now is called busy waiting (also sometimes referred as polling), and yes its inefficient in terms of processor usage and also in terms of energy usage. You code executes whenever the OS allows it, and in doing so it prevents the use of a CPU for other work, or when there is no other work it prevents the CPU from taking a nap, wasting energy (heating the CPU, draining the battery...).
What you should do is put your thread to sleep until the time where you want to do something arrives. This allows the CPU to perform other tasks or go to sleep.
There is a method on java.lang.Thread to do just that: Thread.sleep(long milliseconds) (it also has a cousin taking an additional nanos parameter, but the nanos may be ignored by the VM, and that kind of precision is rarely needed).
So first you determine when you need to do some work. Then you sleep until then. A naive implementation could look like that:
public static void waitUntil(long timestamp) {
long millis = timestamp - System.currentTimeMillis();
// return immediately if time is already in the past
if (millis <= 0)
return;
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
This works fine if you don't have too strict requirements on precisely hitting the time, you can expect it to return reasonably close to the specified time (a few ten ms away probably) if the time isn't too far in the future (a few secs tops). You have however no guarantees that occasionally when the OS is really busy that it possily returns much later.
A slightly more accurate method is to determine the reuired sleep time, sleep for half the time, evaluate required sleep again, sleep again half the time and so on until the required sleep time becomes very small, then busy wait the remaining few milliseconds.
However System.currentTimeMillis() does not guarantee the actual resolution of time; it may change once every millisecond, but it might as well only change every ten ms by 10 (this depends on the platform). Same goes for System.nanoTime().
Waiting for an exact point in time is not possible in high level programming languages in a multi-tasking environment (practically everywhere nowadays). If you have strict requirements, you need to turn to the operating system specifics to create an interrupt at the specified time and handle the event in the interrupt (that means assembler or at least C for the interrupt handler). You won't need that in most normal applications, a few ms +/- usually don't matter in a game/application.
As #ChrisK suggests, you could simplify by just making a direct call to System.currentTimeMillis().
For example:
long time = 0;
do
{
time = System.currentTimeMillis();
} while (time % 5000 != 0);
Note that you need to change the comparison value to 5000 because the representation of the time is in milliseconds.
Also, there are possible pitfalls to doing any comparison so directly like this, as the looping call depends on processor availability and whatnot, so there is a chance that an implementation such as this could make one call that returns:
`1411482384999`
And then the next call in the loop return
`1411482385001`
Meaning that your condition has been skipped by virtue of hardware availability.
If you want to use a built in scheduler, I suggest looking at the answer to a similar question here java: run a function after a specific number of seconds
You should use
System.nanoTime()
instead of
System.currentTimeMillis()
because it returns the measured elapsed time instead of the system time, so nanoTime is not influenced by system time changes.
public class Synchronizer
{
public static void timeInSync()
{
long lastNanoTime = System.nanoTime();
long nowTime = System.nanoTime();
while(nowTime/1000000 - lastNanoTime /1000000 < 5000 )
{
nowTime = System.nanoTime();
}
}
}
The first main point is that you must never use busy-waiting. In java you can avoid busy-waiting by using either Object.wait(timeout) or Thread.sleep(timeout). The later is more suitable for your case, because your case doesn't require losing monitor lock.
Next, you can use two approaches to wait until your time condition is satisfied. You can either precalculate your whole wait time or wait for small time intervals in loop, checking the condition.
I will illustrate both approaches here:
private static long nextWakeTime(long time) {
if (time / 1000 % 5 == 0) { // current time is multiple of five seconds
return time;
}
return (time / 1000 / 5 + 1) * 5000;
}
private static void waitUsingCalculatedTime() {
long currentTime = System.currentTimeMillis();
long wakeTime = nextWakeTime(currentTime);
while (currentTime < wakeTime) {
try {
System.out.printf("Current time: %d%n", currentTime);
System.out.printf("Wake time: %d%n", wakeTime);
System.out.printf("Waiting: %d ms%n", wakeTime - currentTime);
Thread.sleep(wakeTime - currentTime);
} catch (InterruptedException e) {
// ignore
}
currentTime = System.currentTimeMillis();
}
}
private static void waitUsingSmallTime() {
while (System.currentTimeMillis() / 1000 % 5 != 0) {
try {
System.out.printf("Current time: %d%n", System.currentTimeMillis());
Thread.sleep(100);
} catch (InterruptedException e) {
// ignore
}
}
}
As you can see, waiting for the precalculated time is more complex, but it is more precise and more efficient (since in general case it will be done in single iteration). Waiting iteratively for small time interval is simpler, but less efficient and precise (precision is dependent on the selected size of the time interval).
Also please note how I calculate if the time condition is satisfied:
(time / 1000 % 5 == 0)
In first step you need to calculate seconds and only then check if the are multiple of five. Checking by time % 5000 == 0 as suggested in other answer is wrong, as it is true only for the first millisecond of each fifth second.
I need to add time delay between cycle flow like this:
public boolean timeDelay(int seconds) {
// 1000000000 ns = 1 s
if (/* some system method to start calculate time in seconds*/ == seconds) {
return true;
} else {
return false;
}
}
public void renderEnemies() {
for (int w = 0; w < wave.size(); w++) {
while(timeDelay(2)){
(wave.get(w)).render();
}
}
}
Maybe my thinking isn't good, but I need to do like this...
wave --> ArrayList of enemies in my game
Render enemies is in game loop after pressing button "NextWave" and I need to spawn them with delay between them like a --> 2s * 2s * 2s * 2s * 2s *
where * is enemy...
Can you help me?
Try:
Thread.sleep(1000);
and use a try-catch.
You should probably thread it and use sleep as #curiosu mentions.
However, if you don't want to use sleeps/multiple threads but do want it to be pseudo real time (not turn based) you'll need a driving loop at the top of your game like so:
boolean keepPlaying = true;
while(keepPlaying) {
doNpcStep()
doPlayerStep()
keepPlaying = !isGameOver()
}
Each of these steps needs to run in a very small time slice, then in the doNpcStep function you get the current time, find the offset from a start time and run any action that should happen by now.
You could, for example, do this by keeping a min priority queue where priority is equal to the time they should execute by (in ms since start of java epoch). Then take all elements off the queue that are less than or equal to current time and run them, placing new occurrences onto the queue as necessary.
In essence this is a simulation of running a player and npc thread, where you are in charge of how much time each gets to run for.
try putting an infinite while loop
while(1)
{
if(/*method to calc time*/ == seconds)
return true;
}
return false;
I'm assuming that you want to start spawning enemies after 'seconds' time, so always a 'true' should be returned after 'seconds' time has passed. Your method should keep track from what time it has to start counting the seconds. You can call that function when 'NextWave' button is pressed where a variable can increment itself in multiples of 'seconds' so that you can keep track of elapsed time.
Hope this helps.
Recently, I've been getting into Java Game programming. I have learned Java before, but this is my first time with Graphics, Game Loops etc.
I followed this tutorial for a Game Loop, and it's working pretty well.
There is nothing wrong with it, but I just can't figure out why I am thread.sleeping the code, and whats the point of it.
If anyone could explain what start, elapsed and running do, and why I am doing thread.sleep(wait) then I would be super appreciative!
GAME LOOP (Remember, it works, I just don't know why):
while (running) {
start = System.nanoTime();
update();
draw();
drawToScreen();
elapsed = System.nanoTime() - start;
wait = targetTime - elapsed / 1000000;
if (wait < 0) {
wait = 5;
}
try {
Thread.sleep(wait);
} catch (Exception e) {
Game.logger.log("ERROR! Printing Stacktrace...");
e.printStackTrace();
}
}
}
Well, running is a flag that can be set to false to terminate the game.
start and elapsed are used to measure the time one round in the loop took. You are waiting to not make the game run too fast. If you are moving elements with a set speed, then having the game loop run too fast makes them also move too fast. That can lead to a bad user experience, since the user might not be fast enough to play the game.
Additionally, any animation doesn't run smooth anymore without the waiting. It will speed up and slow down depending on how fast your code executes.
Just continue with the tutorial, and when are at the point where you make something move, remove the waiting and see what happens.
EDIT
The code makes a round in the loop take about targetTime. It's unit is milliseconds. So to calculate the frame rate, just divide 1000 / targetTime.
start is the time before the game logic runs. elapsed is the amount of time that it takes for the game logic to run. running is a boolean (true/false) variable that determines whether the game should continue. Thread.sleep(wait) is a method that delays for a certain amount of time.
The goal is to keep the amount of time between frames roughly constant by delaying, so that the animations don't run faster or slower depending on how fast your computer processor is running.
It appears the code aims to be executed targetTime seconds. So you count how much time has already passed (elapsed), and then calculate how much to wait (divide it to get your remaining time in miliseconds, required for methon sleep(wait)).
One purpose of such waiting is often forcing some time between repainting to the screen.
To get your FPS, one way would be to slightly change your code:
long prevStart = 0; //just initialize. First FPS is of course wrong, next get fine.
double FPS = 0;
while (running) {
start = System.nanoTime();
FPS = 1 / double(start - prevStart);
prevStart = start;
update();
draw();
drawToScreen();
elapsed = System.nanoTime() - start;
wait = targetTime - elapsed / 1000000;
if (wait < 0) {
wait = 5;
}
try {
Thread.sleep(wait);
} catch (Exception e) {
Game.logger.log("ERROR! Printing Stacktrace...");
e.printStackTrace();
}
}