Time-efficient Gameloop in J2ME - java

I've done a series of questions about J2ME Game developing, and in a recent one, Neil Coffey commented
As a side issue-- do you REALLY want
to do 100 ticks/second in a J2ME game?
As I think sb has mentioned, you
should really also sleep to the next
desired wake-up point, not a fixed
duration each time.
For some reason, that thing stuck in my mind and now I want the answers, what do I need to make my gameloop sleep to the desired wake-up point, I don't really know where is that point xD (theoretically speaking).
For the sake of feedback, this is a simplified version of my gameloop:
public void run() {
Graphics g = this.getGraphics();
while (running) {
long diff = System.currentTimeMillis() - lastLoop;
lastLoop = System.currentTimeMillis();
input();
this.level.doLogic();
render(g, diff);
try {
Thread.sleep(10);
} catch (InterruptedException e) {
stop(e);
}
}
}
Thanks for your help!!

There is an excellent article on game loops here, if you haven't read it already.
From my experience writing J2ME games, you'll want to minimize how much you do anything in a game loop, as a poorly written game loop can quickly drain a phones puny battery. That is, if you're rendering ever 10 milliseconds, make sure to check to see if anything has changed, and if not, skip it.

If you decide that you want to render every 10 milliseconds, then you:
loop {
- record current time; render
- do input/logic
- check the current time, and calculate elapsed time
- if less than 10 ms has elapsed, calculate the remaining time (10 millis - elapsed time); sleep for this duration
}
I understand that there may be issues with timer resolution (for example, Thread.sleep(10) may not sleep for exactly 10 ms; and System.currentTimeMillis() may not return results with granularity down to 1 ms). This is platform dependent.

Related

Make a simple timer in Java

I can't seem to figure out how to make a simple timer in java. All I need it to do is just display time, really. So just a start method, and it keeps counting up like 0:00, 0:01, 0:02, etc. I've seen some other similar forum posts on this, but all the code is kind of complicated for my level of understanding; I'm kind of new to java. But it shouldnt be that hard to make a timer that just performs such a basic function? If anyone could help it would be greatly appreciated :)
This is not difficult. However, I would caution you that I have seen some very confused answers on stack overflow, in some cases shockingly poor coding habits, so be very careful. First let me answer the question.
If seem that the biggest mistake that programmers make in implementing a timer, is thinking that they need something to keep track of the current time. That is, they write some sort of loop that increments a variable every second or some such silly thing. You do not need to write code to keep track of the time. The function System.currentTimeMillis() will do that for you, and it does it quite accurately.
Timer code will involve two aspects which many programmers mix up:
calculation of the time
refresh of the display
All you need to do to calculate the time to display, is to record the time that the timer started:
long startTime = System.currentTimeMillis();
Later, when you want to display the amount of time, you just subtract this from the current time.
long elapsedTime = System.currentTimeMillis() - startTime;
long elapsedSeconds = elapsedTime / 1000;
long secondsDisplay = elapsedSeconds % 60;
long elapsedMinutes = elapsedSeconds / 60;
//put here code to format and display the values
The biggest mistake that programmers make is to think they need a variable to hold the current time and then to write code to increment that variable every second, e.g. something called "elapsedSeconds" which they maintain. The problem is that you can schedule code to be called every second, but there is no guarantee of exactly when that code will be called. If the system is busy, that code might be called quite a bit later than the second. If the system is extremely busy (for example page fetching from a faulty disk) it could actually be several seconds late. Code that uses the Thread.sleep(1000) function to loop every second will find that the error builds up over time. If sleep returns 300ms late one time, that error is compounded into your calculation of what time it is. This is all completely unnecessary because the OS has a function to tell you the current time.
The above calculation will be accurate whether you run this code every second, 100 times a second, or once every 3.572 seconds. The point is that currentTimeMillis() is the accurate representation of the time regardless of when this code is called -- and that is an important consideration because thread and timer events are not guaranteed to be accurate at a specific time.
The second aspect of a timer is refresh of the display. This will depend upon the technology you are using to display with. In a GUI environment you need to schedule paint events. You would like these paint events to come right after the time that the display is expected to change. However, it is tricky. You can request a paint event, but there may be hundreds of other paint events queued up to be handled before yours.
One lazy way to do this is to schedule 10 paint events per second. Because the calculation of the time does not depend on the code being called at a particular point in time, and because it does not matter if you re-paint the screen with the same time, this approach more or less guarantees that the displayed time will show the right time within about 1/10 of a second. This seems a bit of a waste, because 9 times out of 10 you are painting what is already on the screen.
If you are writing a program with animation of some sort (like a game) which is refreshing the screen 30 times a second, then you need do nothing. Just incorporate the timer display call into your regular screen refresh.
If paint events are expensive, or if you are writing a program that does terminal-style output, you can optimize the scheduling of events by calculating the amount of time remaining until the display will change:
long elapsedTime = System.currentTimeMillis() - startTime;
long timeTillNextDisplayChange = 1000 - (elapsedTime % 1000);
The variable timeTillNextDisplayChange holds the number of milliseconds you need to wait until the seconds part of the timer will change. You can then schedule a paint event to occur at that time, possibly calling Thread.sleep(timeTillNextDisplayChange) and after the sleep do the output. If your code is running in a browser, you can use this technique to update the page DOM at the right time.
Note, that there is nothing in this calculation of the display refresh that effects the accuracy of the timer itself. The thread might return from sleep 10ms late, or even 500ms late, and the accuracy of the timer will not be effected. On every pass we calculate the time to wait from the currentTimeMillis, so being called late on one occasion will not cause later displays to be late.
That is the key to an accurate timer. Do not expect the OS to call your routine or send the paint event exactly when you ask it to. Usually, of course, with modern machines, the OS is remarkably responsive and accurate. This happens in test situations where you are not running much else, and the timer seems to work. But, in production, under rare stress situation, you do not want your timer "drifting" because the system is busy.
You can either use Timer class from java.util or another way, which is more complicated, is with Threads. Timer also has thread action, but it's pretty easy to understand to use it.
For creating a simple timer as you explained as per your need , it is very easy to write a code for that. I have written the below code for your reference. If you wish you can enhance it.
import java.util.concurrent.TimeUnit;
public class PerfectTimer {
public static void main(String[] args) throws InterruptedException
{
boolean x=true;
long displayMinutes=0;
long starttime=System.currentTimeMillis();
System.out.println("Timer:");
while(x)
{
TimeUnit.SECONDS.sleep(1);
long timepassed=System.currentTimeMillis()-starttime;
long secondspassed=timepassed/1000;
if(secondspassed==60)
{
secondspassed=0;
starttime=System.currentTimeMillis();
}
if((secondspassed%60)==0)
displayMinutes++;
System.out.println(displayMinutes+"::"+secondspassed);
}
}
}
if you want to update something in the main thread (like UI components)
better to use Handler
Handler h = new Handler();
h.postDelayed(new Runnable() {
#Override
public void run() {
//do something
}
}, 20);
20 - the delay In MS to do something.
and run it in a loop.
I have created a Timer that has everything you might need in it.
I even documented it!
And I also compiled it for faster usage.
Here's an example:
//...
//For demo only!
public static void main(String[]a){
Timer timer=new Timer();
timer.setWatcher(new Timer.TimerWatcher(){
public void hasStopped(boolean stopped){
System.out.print(stopped+" | ");
}
public void timeElapsed(long nano, long millis, long seconds){
System.out.print(nano+", ");
System.out.print(millis+", ");
System.out.print(seconds+" | ");
}
public void timeLeft(long timeLeft){
System.out.print(timeLeft+"\r");
}
});
//Block the thread for 5 seconds!
timer.stopAfter(5, Timer.seconds); //You can replace this with Integer.MAX_VALUE.
//So that our watcher won't go to waste.
System.out.println();
}
//...
This is not for promotion, made this to help people not waste their time in coding classes themselves!

Java timing accuracy on Windows XP vs. Windows 7

I have a bizarre problem - I'm hoping someone can explain to me what is happening and a possible workaround. I am implementing a Z80 core in Java, and attempting to slow it down, by using a java.util.Timer object in a separate thread.
The basic setup is that I have one thread running an execute loop, 50 times per second. Within this execute loop, however many cycles are executed, and then wait() is invoked. The external Timer thread will invoke notifyAll() on the Z80 object every 20ms, simulating a PAL Sega Master System clock frequency of 3.54 MHz (ish).
The method I have described above works perfectly on Windows 7 (tried two machines) but I have also tried two Windows XP machines and on both of them, the Timer object seems to be oversleeping by around 50% or so. This means that one second of emulation time is actually taking around 1.5 seconds or so on a Windows XP machine.
I have tried using Thread.sleep() instead of a Timer object, but this has exactly the same effect. I realise granularity of time in most OSes isn't better than 1ms, but I can put up with 999ms or 1001ms instead of 1000ms. What I can't put up with is 1562ms - I just don't understand why my method works OK on newer version of Windows, but not the older one - I've investigated interrupt periods and so on, but don't seem to have developed a workaround.
Could anyone please tell me the cause of this problem and a suggested workaround? Many thanks.
Update: Here is the full code for a smaller app I built to show the same issue:
import java.util.Timer;
import java.util.TimerTask;
public class WorkThread extends Thread
{
private Timer timerThread;
private WakeUpTask timerTask;
public WorkThread()
{
timerThread = new Timer();
timerTask = new WakeUpTask(this);
}
public void run()
{
timerThread.schedule(timerTask, 0, 20);
while (true)
{
long startTime = System.nanoTime();
for (int i = 0; i < 50; i++)
{
int a = 1 + 1;
goToSleep();
}
long timeTaken = (System.nanoTime() - startTime) / 1000000;
System.out.println("Time taken this loop: " + timeTaken + " milliseconds");
}
}
synchronized public void goToSleep()
{
try
{
wait();
}
catch (InterruptedException e)
{
System.exit(0);
}
}
synchronized public void wakeUp()
{
notifyAll();
}
private class WakeUpTask extends TimerTask
{
private WorkThread w;
public WakeUpTask(WorkThread t)
{
w = t;
}
public void run()
{
w.wakeUp();
}
}
}
All the main class does is create and start one of these worker threads. On Windows 7, this code produces a time of around 999ms - 1000ms, which is totally fine. Running the same jar on Windows XP however produces a time of around 1562ms - 1566ms, and this is on two separate XP machines that I have tested this. They are all running Java 6 update 27.
I find this problem is happening because the Timer is sleeping for 20ms (quite a small value) - if I bung all the execute loops for a single second into wait wait() - notifyAll() cycle, this produces the correct result - I'm sure people who see what I'm trying to do (emulate a Sega Master System at 50fps) will see how this is not a solution though - it won't give an interactive response time, skipping 49 of every 50. As I say, Win7 copes fine with this. Sorry if my code is too large :-(
Could anyone please tell me the cause of this problem and a suggested workaround?
The problem you are seeing probably has to do with clock resolution. Some Operating Systems (Windows XP and earlier) are notorious for oversleeping and being slow with wait/notify/sleep (interrupts in general). Meanwhile other Operating Systems (every Linux I've seen) are excellent at returning control at quite nearly the moment specified.
The workaround? For short durations, use a live wait (busy loop). For long durations, sleep for less time than you really want and then live wait the remainder.
I'd forgo the TimerTask and just use a busy loop:
long sleepUntil = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(20);
while (System.nanoTime() < sleepUntil) {
Thread.sleep(2); // catch of InterruptedException left out for brevity
}
The two millisecond delay gives the host OS plenty of time to work on other stuff (and you're likely to be on a multicore anyway). The remaining program code is a lot simpler.
If the hard-coded two milliseconds are too much of a blunt instrument, you can calculate the required sleep time and use the Thread.sleep(long, int) overload.
You can set the timer resolution on Windows XP.
http://msdn.microsoft.com/en-us/library/windows/desktop/dd757624%28v=vs.85%29.aspx
Since this is a system-wide setting, you can use a tool to set the resolution so you can verify whether this is your problem.
Try this out and see if it helps: http://www.lucashale.com/timer-resolution/
You might see better timings on newer versions of Windows because, by default, newer version might have tighter timings. Also, if you are running an application such as Windows Media Player, it improves the timer resolution. So if you happen to be listening to some music while running your emulator, you might get great timings.

Play a sound every N milliseconds

I'm developing a metronome application. The user can select at runtime the bpm, and my app will play the "tick" sound accordingly. The "tick" is a single metronome "shot" (mp3). I tried implementing it using Handler and MediaPlayer, but the metronome is not precise at all.
So I thought about changing the whole approach: when the user choose a new bpm value, I synthesize a new sound by repeating the tick sound X times every N milliseconds, then looping over this runtime created sound.
Is this a valid alternative? How can it be implemented in Android?
The alternative of looping through a synthesized sound seems to be the best choice for now. There was a great session about audio on Google I/O 2013 called High Performance Audio that I would certainly advice watching for having a deeper understanding on how the system works and what problems the developers will face when dealing with the audio latency. At about the 17:00 of the video, there is graph that shows jitter versus callbacks. In the perfect world that does not exist (oh really?), the jitter would be zero for all the scheduled audio callbacks made. But that is not the case, for there are jitters as high as 35 milliseconds or even greater, for the data in the graph was made using an unspecified ICS device and there are certainly worse scenarios than that.
So, as a metronome is a precision tool and these jitters are not good at all, the scheduled playback approach should be left aside. I even made an reasonably realiable metronome work with a synthesized sound using AudioTrack.
Hope it helps ^^
You could try to use a TimerTask scheduled for fixed-rate execution on a Timer.
Timer and TimerTask are both part of the Android SDK (and Java SE). The executions do not delay because of execution time of the previous event.
Timer timer = new Timer("MetronomeTimer", true);
TimerTask tone = new TimerTask(){
#Override
public void run(){
//Play sound
}
};
timer.scheduleAtFixedRate(tone, 500, 500); //120 BPM. Executes every 500 ms.
You can then cancel the TimerTask when you need to change the BPM.
tone.cancel();
tone = new TimerTask(){...}
timer.scheduleAtFixedRate(tone, 1000, 1000); //60 BPM. Executes every 1000 ms.
Another possibility that may meet your requirements (from your comments) is spinning a thread and checking System.nanoTime() and sleeping in increments but spinning when you get close to wake up.
long delayNanos = 500000000;
long wakeup = System.nanoTime() + delayNanos; //Half second from right now
long now;
while(!done){
now = System.nanoTime();
//If we are less than 50 milliseconds from wake up. Spin away.
if(now <= wakeup - 50000000){
//Sleep in very small increments, so we don't spin unrestricted.
Thread.sleep(10);
}
if(now >= wakeup){
//Play sound
wakeup += delayNanos;
}
}
When this play sound is called
mSoundManager.playSound(1);
Android waits until that call is finished, then you call
mHandler.postAtTime(this, SystemClock.uptimeMillis() + 200);
however, if you reverse those calls, you may find that the timing is more accurate.
mHandler.postAtTime(this, SystemClock.uptimeMillis() + 200);
mSoundManager.playSound(1);
You can't count on your sound taking exactly the same amount of time to play, so telling the handler to post first is a bit better. Still not ideal, however.

Using multiple timers in a Java application with animation

I'm writing a Java Application that will side scroll sheet music across the screen and then when it crosses a middle line, it will play the note(s).
It will have a variable speed based on the beats per minute.
Every quarter of a beat I need to have a "tick" function that will get the next note (if any) and start its animation. To calculate this tick I have a function 60000ms/bpm/4. This will be separate from the animation timer, because the repaint should probably be called at some constant rate.
So I'm thinking I need Util Timer for the "ticks" and a swing timer for the JPanel and drawing in the paintComponent() method.
My question is: What would be the best practice for accomplishing this? I've done a fair amount of Java programming, but no Swing or animations so I would like to learn the best way to do this.
Thanks
Nate
There is no reason to use Timer or TimerTask to solve this problem.
In this case, you have a series of notes, and when you start playing, you can calculate ahead of time, the exact time that each and every note should play. I am assuming that you already have some sort of loop that is updating the display at a steady rate. (e.g. 30 refreshes per second, or something like that). Given such a loop, all you need is an event oriented class that can tell you whether it is time to play a note.
long noteTime[] = new long[numberOfNotes];
long startTime = System.currentTimeMillis();
Declare the above array. Then walk through all the notes in the song, and calculate the time that each note is expected to play. Say you have qurter notes, the first note will play at startTime, the second one beat after startTime, the third two beats after start time, etc. This is where you calculate the time for a beat and use it. Just calculate the actual time values for each note to play.
Then, in the middle of your event loop that is refreshing the display, include the following code:
int nextNote = 0;
while (event_loop_condition) {
.
.
.
if (System.currentTimeMillis()>noteTime[nextNote]) {
playNote(nextNote++);
}
.
.
.
}
The point is that you already have an event loop, all you need to know is whether it it time yet to play the note, and this will do that for you.
On the other hand, if you are not handling the refresh, and you really do want to do this on a thread, the follow method can be called on a thread, and it will play all the notes at the correct times:
playAllNotes() {
for (int i=0; i<numberOfNotes; i++) {
Thread.sleep(noteTime[i]-System.currentTimeMillis());
playNote(i);
}
}
The sleep statement will delay until the time that the note should be played, and will play it at that time. Then it will sleep until the time for the next note to be played.
The important thing to notice about both methods, is that any delay in playing a note is NOT compounded for the next note. Say some system utility kicks in and delays one note by 50ms. The next note will not be delayed by this, because you calculated all the times for all the notes to be played up front. Given that threads are competing for CPU time, you will have thread/process contention, and there will be small variances in the time that notes are played, but they will never compound!
A lot of programmers inappropriately use timers (See discussion of Timers) on my website if you want to know more.

Measuring time spent in application / thread

I am writing a simulation in Java whereby objects act under Newtonian physics. An object may have a force applied to it and the resulting velocity causes it to move across the screen. The nature of the simulation means that objects move in discrete steps depending on the time ellapsed between the current and previous iteration of the animation loop; e.g
public void animationLoop() {
long prev = System.currentTimeMillis();
long now;
while(true) {
long now = System.currentTimeMillis();
long deltaMillis = now - prev;
prev = now;
if (deltaMillis > 0) { // Some time has passed
for (Mass m : masses) {
m.updatePosition(deltaMillis);
}
// Do all repaints.
}
}
}
A problem arises if the animation thread is delayed in some way causing a large amount of time to ellapse (the classic case being under Windows whereby clicking and holding on minimise / maximise prevents a repaint), which causes objects to move at an alarming rate. My question: Is there a way to determine the time spent in the animation thread rather than the wallclock time, or can anyone suggest a workaround to avoid this problem?
My only thought so far is to contstrain deltaMillis by some upper bound.
Have you considered using something like a timer instead of spinning in a loop?
TimerTask tt = new TimerTask(){
long prev = System.currentTimeMillis();
public void run(){
long now = System.currentTimeMillis();
for (Mass m : masses) {
m.updatePosition(now-prev);
}
prev = now;
}
}
new Timer(true).schedule(tt, 1000, 1000) ;
This way you are guaranteed to at least have some delay between the update of your objects so you shouldn't have a bunch of repaints consecutively as with the while(true) loop, and if the thread is delayed you will not got an immediate re-execution of the task, from the docs: "In fixed-delay execution, each execution is scheduled relative to the actual execution time of the previous execution."
I found javax.swing.Timer.html particularly helpful for this. Here's an example that models elastic collisions among spherical particles and the walls of a container.
Addendum: This related approach may help de-couple the model from the view. A separate thread models the system's evolution, while the view renders a "snapshot" of the model at a fixed rate.
In either case, I cap the rate to accommodate the slowest target platform.
You might like to read this article entitled "Java: Getting Thread Time with ThreadMXBean".
Basically, there is a class ThreadMXBean that enables you to get time spent in particular Thread. I haven't tried that, but the methods (and examples from article I mentioned) look promising, so I think you will be able to accomplish what you want with this.
I would use an animation library for doing the animation instead of reinventing the wheel. Here are two good choices:
The Timing Framework
Trident

Categories

Resources