Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (475)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (530)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Sleep based timer hack  (Read 6897 times)
0 Members and 1 Guest are viewing this topic.
Offline Jeff

JGO Coder




Got any cats?


« Posted 2002-10-24 00:19:21 »

This one gets asked alot, so I thought I'd post it seperately.

Attributions:  
Contributed to the community by TheLorax.
This version from mbishop's pacman clone.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
// SleepTimer.java
// Here we have "thelorax"'s famous "sleep" timer.  This uses Thread.sleep()
// to get higher-resolution timing under Windows 9x platforms.
public class SleepTimer implements Runnable {

   // Number of elapsed ticks.  A tick is fired every time a sleep occurs.
  private int ticks;

   // The Thread that will be run.
  private Thread timerThread;

   // Our current delay and our desired delay.
  private long msDelay, targetMs;

   // Do we let this Thread correct itself?
  private boolean autoCorrection = true;

   // Is this Thread running?
  private boolean running = false;

   // Difference since last tick.
  private long timeDiff;

   // Desired frames per second.
  private int autoLength;

   // Start time and end time.
  private long startTime, endTime;

   // Of course we want a high priority to do our timing right.
  public SleepTimer() {
      timerThread = new Thread(this);
      timerThread.setPriority(Thread.MAX_PRIORITY);
      timerThread.setDaemon(true);
   }

   public int getTickCount() {
      return ticks;
   }

   // I added this so I could see the number of ticks missed
  // on a per-second basis.
  public void resetTickCount() {
      ticks = 0;
   }

   public void startTimer() {
      running = true;
      timerThread.start();
   }

   public void stopTimer() {
      running = false;
      try {
         timerThread.join();
      }
      catch (Exception e) {}
   }

   // We set auto-correction with a desired frames (ticks) per second.
  public void setAutoCorrection(boolean on, int sampleLength) {
      autoCorrection = on;
      autoLength = sampleLength;
   }

   public void setDelay(int tmsDelay) {
      msDelay = tmsDelay;
      targetMs = msDelay;
   }

   // Sleeps the specified amount, lets other Threads know, then
  // corrects itself if auto-correcting is set.
  public void run() {
      startTime = System.currentTimeMillis();
      try {
         while (running) {
            Thread.sleep(msDelay);
            ticks++;

            synchronized(this) {
               notifyAll();
            }
            if (autoCorrection && (ticks % autoLength == 0)) {
               endTime = System.currentTimeMillis();
               timeDiff = ((endTime - startTime) / autoLength) - targetMs;
               startTime = endTime;
               if (timeDiff > 0) {
                  msDelay--;
               }
               if (timeDiff < 0) {
                  msDelay++;
               }
            }
         }
      }
      catch (Exception e) {
         System.err.println("Exception in Timer Thread.");
         e.printStackTrace();
      }
   }
}

Got a question about Java and game programming?  Just new to the Java Game Development Community?  Try my FAQ.  Its likely you'll learn something!

http://wiki.java.net/bin/view/Games/JeffFAQ
Offline GergisKhan

Junior Member




&quot;C8 H10 N4 O2&quot;


« Reply #1 - Posted 2002-10-24 16:56:46 »

Thanks Jeff.  I had not wanted to post it until giving TheLorax a chance to do so, but you beat me to the punch. Smiley

gK

"Go.  Teach them not to mess with us."
          -- Cao Cao, Dynasty Warriors 3
Offline Jeff

JGO Coder




Got any cats?


« Reply #2 - Posted 2002-10-24 19:44:44 »

Yeah, i had to thin kthis one through carefully as I'm very dilligent about author's rights, beign one myself.

Since Lorax has it publically posted  in the archives though, and mbishop had already posted a link to his source, I assumed an implicit permission to repost.  (If I was wrong guys, tell Chris to remove it and hit me with a wet tuna Smiley )

Got a question about Java and game programming?  Just new to the Java Game Development Community?  Try my FAQ.  Its likely you'll learn something!

http://wiki.java.net/bin/view/Games/JeffFAQ
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline mbishop78

Senior Newbie





« Reply #3 - Posted 2002-10-26 02:05:53 »

Thanks for digging it out and posting it.  I was a bit leery about doing it myself, but he did post it and I did give him credit in the code... Smiley

Michael Bishop
Offline Captain-Goatse

Junior Member




I suck at teh 2D. XBOX IS BIG LOL!111


« Reply #4 - Posted 2002-11-01 09:50:07 »

I have been trying to understand how this timer hack works, but it seems to be that I get randomly error in timerthread where time out value is negative. I have figured out that his has something to do with too small autoCorrection values. The picture thread just freezes.

I've also found out that with this "hack" i see slowdowns after a period of time and it is repetitive.

Can someone please lighten me up on the use of this thing before I implement it into my game. Otherwise it seems to be really great, except for those two little faults on my side.

I'm also kind of confused with this 1.4 fullscreen rendering because of the lack of paint and update methods in away. I guess it just time to get used to it. Does anyone have any article where I could review the basic principles of fullscreen animation? It seems like a lot of the AWT rules are now old and almost useless.
Offline mbishop78

Senior Newbie





« Reply #5 - Posted 2002-11-01 12:57:02 »

This is all the code I used to get it running at "fps" fps.

frameTimer = new SleepTimer();
frameTimer.setDelay(1000 / fps);
frameTimer.setAutoCorrection(true, fps);
frameTimer.startTimer();

I've never had it throw an error before.  Then again, I haven't run it over 60 frames-per-second.

Michael Bishop
Offline Captain-Goatse

Junior Member




I suck at teh 2D. XBOX IS BIG LOL!111


« Reply #6 - Posted 2002-11-02 05:28:51 »

Hmm... that makes me wonder what is wrong with my code then...

The animation is smooth for certain amount of time and then it kind of *ticks*. Then it starts over again. I guess I have to start looking through the render loop to see if I can find any nasty code from there.
Offline mbishop78

Senior Newbie





« Reply #7 - Posted 2002-11-06 13:00:49 »

That sounds suspiciously like garbage collection without seeing any code.  Definitely avoid creating objects in your render loop and run it against a profiler.

Michael Bishop
Offline Captain-Goatse

Junior Member




I suck at teh 2D. XBOX IS BIG LOL!111


« Reply #8 - Posted 2002-11-06 13:08:59 »

The only object I'm creating is the graphics object. I guess I have to figure out a way to create it outside, but would this really affect? I mean its very simple a aquare moving across the screen and the player rotates around its origin according to mouse and then a moves whatever direction the player decides.

Could the affinetransform be the reason? Now its making the pictures on the roll, but should I make and array of transfromation where the correct transformation gets called each and every time?

The memory usage would be a lot greater, because for smooth animation it would have to be like 70 images or so. 360/5. And then I would have to forget affinetransfroms.

It can't be the graphics 2d object can it? So many other programs create it at the beginning of rendering loop so I highly doubt so.
Offline Captain-Goatse

Junior Member




I suck at teh 2D. XBOX IS BIG LOL!111


« Reply #9 - Posted 2002-11-06 16:47:30 »

Hmm I still get the negative timeout error at java native code. Perhaps my garbage collection is wrong and this is really messing up the system. The animation runs really great for the time it twiches. Then after a while the screen freezes dues the negative timeout error.

Edited to say:


It's the mouse rotating the player which causes the problem. Because of the player direction has to be updated all the time, the animation twiches at some point. I will find out why.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Jeff

JGO Coder




Got any cats?


« Reply #10 - Posted 2002-11-07 21:01:04 »

Quote
I
I'm also kind of confused with this 1.4 fullscreen rendering because of the lack of paint and update methods in away. I guess it just time to get used to it. Does anyone have any article where I could review the basic principles of fullscreen animation? It seems like a lot of the AWT rules are now old and almost useless.


Yep you are going around the entire AWT paint mechanism when you do Buffer Flipping (and for darn good reasons, you need more control and more efficiency then AWT gives yo uto do cutting edge games.)

Im not sure hwo much there is to explain but Ill do so in the BufferFlipping thread...

Got a question about Java and game programming?  Just new to the Java Game Development Community?  Try my FAQ.  Its likely you'll learn something!

http://wiki.java.net/bin/view/Games/JeffFAQ
Offline Ssnake

Innocent Bystander




Java games rock!


« Reply #11 - Posted 2002-11-08 19:32:20 »

How is this timer used?
Every time I set this up and call wait() on my main thread,
nothing happens (I get no notifyAll()'s).

Can someone post a sample main() method that sets this
timer up and waits for it to notify it so I can paint?

Thanks  Huh
Offline erikd

JGO Ninja


Medals: 16
Projects: 4
Exp: 14 years


Maximumisness


« Reply #12 - Posted 2002-11-09 21:59:27 »

This could be a stupid idea, but maybe javax.sound.sampled could be misused to mimic a high(-er) resolution timer?
I was thinking about setting up a dataline and fill the buffer with exactly the amount of samples that would last one frame and then wait for the buffer to empty before going to the next frame.

I haven't got around to try it yet, but I think it could work in theory, although there could be some performance loss.

Just a thought...

Smiley Erik

TheLorax
Guest
« Reply #13 - Posted 2002-11-12 01:47:38 »

Quote
Hmm I still get the negative timeout error at java native code. Perhaps my garbage collection is wrong and this is really messing up the system. The animation runs really great for the time it twiches. Then after a while the screen freezes dues the negative timeout error.



Ok, I'm here...  ( dropped off the planet for a while, glad to see my work still floating round ).

The exception is because you might be timing something much smaller than I had expected and the "correction" value starts to occalate and then the sleep(x) drops to -something.  I could probably fix it by only taking a percentage or some sort of logorithmic like function so the closer you get to zero the less it actually reduces the value by.

Hmmm.. minimally it should probably throw a runtime exception if the sleep value drop to below zero.
TheLorax
Guest
« Reply #14 - Posted 2002-11-12 02:02:21 »

Quote
This could be a stupid idea, but maybe javax.sound.sampled could be misused to mimic a high(-er) resolution timer?
I was thinking about setting up a dataline and fill the buffer with exactly the amount of samples that would last one frame and then wait for the buffer to empty before going to the next frame.

I haven't got around to try it yet, but I think it could work in theory, although there could be some performance loss.

Just a thought...

Smiley Erik


Just to short circuit that idea, it doesn't work.  I tried it out, but soon found out that databuffers are very finiky.

They appear only to work in chucnks that don't translate into java very well.  It works great for streaming, but your "resolution" is copletley dependat on the native "chunk" size normally something like 8192k ( 44.1k 16 bit stereo ) would equal a maximum timer resolution of 21 times/second... ugh.

If you think you can use the get availible ( or whatever it's called ) that only works on chunks too, it's hopeless.  Since it's non-blocking up to the point where it runs out of space and blocking after that you can't even depend on it to take a specific ammount of time to add a specific number of samples.

The only ACCURATE timer availible is the J3d one, but even there you cannot even depend on an accurate resolution value since under lunix the value is screwed up and need to be caluculated dynamicaly.

Oyh...

You might think sun does not want us to succeed.
Offline erikd

JGO Ninja


Medals: 16
Projects: 4
Exp: 14 years


Maximumisness


« Reply #15 - Posted 2002-11-12 06:24:57 »

Quote
Just to short circuit that idea, it doesn't work.  I tried it out, but soon found out that databuffers are very finiky


Yes you're right it doesn't work, just tried it yesterday night Sad
Thanks for the explanation, though. It does clarify some things...

I heard (but I can't confirm it) that the above solution where the timer runs in a seperate thread doesn't work well on linux and/or unix. Don't know if that's true (can someone confirm it?), but I have a solution which slows down a ('main') thread which seems to work well (at least on windows systems but I heard on other platforms too). Complete with (automatic) frameskip option. If someone's interested, I can post it.

Greetings,
Erik

Offline Woz

Senior Newbie




A Troll who lives in a hole


« Reply #16 - Posted 2002-11-12 11:41:18 »

As I mentioned on the old board, there is the chance the new Linux Kernal (sorry Kernel!) might fix the thread problem.

High performance threading turns up in version 2.6 (or version 3.0 if they decide to change the name) and here is a bit of an article for your interest:
http://www.onlamp.com/pub/a/onlamp/2002/11/07/linux_threads.html

Anybody been able to try it with Java yet?? (Not even sure if it's available yet.) http://www.kernel.org/ does not seem to have it.

Utterly disapointed with the sound syncing system, it may be that it works fine on some JVM's though, as I never tried it with IBM's JVM.http://www-106.ibm.com/developerworks/java/.

At the end of the day the only system that works reliably (when given 100% cpu) is running unlimited, which is what I use as a fall back method.

But this means using Doubles/Floats/1.15.16 fixed point for all your counters, co-ords etc which can look messy because this means you have to deal with 1.5 pixels of travel rather than just whole integers.

Threads can behave very wierdly, if you sync on one they are typically stable (+-5% variation), if you don't sync on them (say your frame rate drops below 60Hz) then expect the Thread to become unstable (-15% so 60Hz drops to 51Hz).

This really annoys me as ALL IBM compatable PC's (from the very first 64K tape machine upwards) have a 8253 timer chip in (PC speaker) which gets a 1,193,180Hz signal from the PC's oscilator (8284 I believe). And can be read (albeit as a 16 bit counter, but that is not difficult to get round).

Want to know how many bytes this code takes?

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
I8_Ctrl_Port     EQU 043h
I8_T2_Port       EQU 042h

  mov  al,04h
  out  I8_Ctrl_Port,al

  in   al,I8_T2_Port  ;Get Low Byte Of Counter.
  rol  ax,8
  in   al,I8_T2_Port  ;Get High Byte Of Counter.
  rol  ax,8


[b]Can even be done in Turbo Pascal![/b]

  Port[ $43 ] := $04;
  Read_Timer :=( Port[$42] SHL 8 )+ Port[ $42 ];


Thats about 14 bytes that execute in under 30 clock cycles ( Port IO is still very slow). And do they use it? Do they hell...


What you need to be thinking about is where are the hi-res timers located within a PC, most of them are off limits because of Java, but there must be a way to access the high res timer in the network card.

I'm sure the TCP/IP packets get date stamped, what if you could route out a packet that was received imediately and read the time fields (but I don't think this is accessable in Java). But interestingly you can set/catch a timeout value (unstated accuracy - could be minutes!).

Have not had the time to try it yet, anybody want to have a go?

ServerSocket.SetSoTimeout( int ); Looks interesting, available in JDK1.1 too.

public void setSoTimeout(int timeout)  throws SocketException

Or some variation on this? Probably causes a security exception in Applets through...


All the best,
-------
Woz.

Offline MGodehardt

Junior Member




why does the chicken cross the road?


« Reply #17 - Posted 2002-12-05 16:36:43 »

i tried a lot to get a stable fps, but nothing works, the System.currentTimeMillis is so unaccurat.

Instead i use a seperate TimerThread class with a run method like this

     public void run()
   {
       System.out.println("> timer thread started " + getPriority());

       isRunning = true;
       
       while ( isRunning )
       {
           try
           {
               Thread.sleep(1);
           }
           catch ( Exception ex )
           {
           }

           synchronized ( itsMutex )
           {
               itsTickCount++;
           }
           MainFrame.itsMainFrame.timerTick(itsTickCount);
       }
   }

this thread runs at max priority

   /**********************************************************************************************
    * setTickCount
    *********************************************************************************************/
     public void setTickCount(long ticks)
   {
       itsTickCount = ticks;
   }
   
   /**********************************************************************************************
    * getTickCount
    *********************************************************************************************/
     public long getTickCount()
   {
       long value = 0;
       
       synchronized ( itsMutex )
       {
           value = itsTickCount;
       }

       return value;
   }

use this as selectors and voila, at a fps of 90 my calculated framerate is 90.0

hope it helps
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

ctomni231 (32 views)
2014-07-18 06:55:21

Zero Volt (28 views)
2014-07-17 23:47:54

danieldean (24 views)
2014-07-17 23:41:23

MustardPeter (25 views)
2014-07-16 23:30:00

Cero (40 views)
2014-07-16 00:42:17

Riven (42 views)
2014-07-14 18:02:53

OpenGLShaders (29 views)
2014-07-14 16:23:47

Riven (29 views)
2014-07-14 11:51:35

quew8 (27 views)
2014-07-13 13:57:52

SHC (63 views)
2014-07-12 17:50:04
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!