Advertisement

[java] Keeping constant framerate

Started by July 18, 2000 07:35 AM
12 comments, last by Tolwyn 24 years, 4 months ago
Anyone know a good way to keep a constant framerate i Java? In other languages I guess you would do some vsync check with the monitor, but you can''t do that in Java... or what? I know about the sleep method in the Thread class, but you will get a problem on a 200Mhz and a 500Mhz computer right?
The sleep method takes an argument in milliseconds, so it should be completely independent of CPU speed. I can''t tell you whether that''s the "correct" way to ensure a constant frame rate or not, though, I haven''t tried it.
I am a Jedi, like my father before me
Advertisement
I've never heard of doing a vsynch check with the monitor to get a constant frame rate. The way I usually hear about it is, time your update, then make movements based on the time it took for the update. But I usually put my drawing routine in a thread and my update (game engine) in a thread. In theory I guess it woun't insure a constant frame rate, but as computers get faster, the frame rate should peak due to the constant sleep time of the thread. If the game engine only takes 1 millisecond to update and you are sleeping for 200 after that, then you aren't going to see much difference in a computer that takes 10 milliseconds to update and still sleeps for 200. The Thread.sleep() way should scale nicely as computers get faster, but not for slower computers.

Edited by - Jim_Ross on July 18, 2000 11:06:56 AM
sleep() is based on System time, so it is independent of CPU speed. (System clock drift is a different story)

Updating the screen based on a fixed rate timer will effectivly tie the screen to that rate. IE you have a thread that sleeps for 50 milliseconds, then notifies another thread when it wakes up, then goes back to sleep. The second thread is responsable for updating the screen. This second thread would update the screen every 50 millis, or 20 times a second. (More or less)

I would suggest looking into javax.swing.Timer. If you are not using Java2 or Swing you can at least see how Sun implemented their timer class.

ManaSink
(Sorry if this post travels covered ground, I got pulled into a meeting before submitting it.)



Edited by - ManaSink on July 18, 2000 2:00:28 PM
The trick is not to get a constant frame rate that is pointless. What you want to do is update everything based on time and not baised on the fact it is the next frame. This will ensure that a man walking accross the screen will do so at the same speed if your getting 20 fps or 100 fps.

------------------------------

"My sword is like a menacing cloud, but instead of rain, blood will pour in its path." - Sehabeddin, Turkish Military Commander 1438.
------------------------------"My sword is like a menacing cloud, but instead of rain, blood will pour in its path." - Sehabeddin, Turkish Military Commander 1438.
I believe an animation timer would do the trick. Here is an link to an article that discusses high performance animation from Javaone in 1999 (scroll down and click on Slides to see the presentation in PDF format):

http://industry.java.sun.com/javaone/99/event/0,1768,633,00.html
Advertisement
quote: Original post by UraniumRod

The trick is not to get a constant frame rate that is pointless. What you want to do is update everything based on time and not baised on the fact it is the next frame. This will ensure that a man walking accross the screen will do so at the same speed if your getting 20 fps or 100 fps.


Damn, I typed up a reply to this yesterday, I must have forgot to hit submit.

This is 100% true, how fast your game objects (IE, the man) move should not be dependent on how fast your screen updates. Updating the screen 2 times a second or 200 times a second shouldn''t affect how your game objects act. These two items should run at independent rates.

I usually have my game objects responding to game ticks, and my screen display responding to screen ticks. When a screen tick occurs, it updates the display for whatever state the game objects are in. The game objects respond to game ticks so they all run at one pace, which can be faster or slower than the screen update. I *do* update my screen at a fixed rate, because past a certain point, my game (the key being "my") looks the same at 20fps or 100fps, and I can use the CPU time for other tasks like AI and cache mgmt.

I never even considered Tolwyn might be updating game state in his screen update thread (a very bad plan), nice catch UraniumRod.

ManaSink
I have had problems with this too. I would use a Timer and have a consistantly inconsistant framerate. It would be 50 milliseconds then 110, then 50 then 110, if I set it to trigger every 50 ms. With threads I would use sleep but find it would sometines refuse to sleep( 0 milliseconds) or sometimes sleep way too long. Hopefully these issues will be resolved, but I''ve posted this question on a couple java forums and got no answers.
author of the Helping Phriendly Book
Accurate timing is one of the trickiest things in Java.

The Thread.sleep() can (as Icculus points out in the previous post) indeed sleep for 0ms or a lot more than you requested. This is because the sleep() method is dependent on the thread scheduler of the operating system you are using. I noticed couple of years ago how differently even Win95 and WinNT 4.0 behave in this department and I actually coded two ways of waiting for a set time in my application.

Also System.currentTimeMillis() is quite useless when used directly as (at least under Win95/98/NT) it updates about every 50ms. You can try this by making a program that runs in a loop and just prints the milliseconds, you''ll see the reading changes in about 50ms steps (= 20 times per second).

The best solution I''ve found is to use the currentTimeMillis() with averaging (the trick I''m using in GameFrame) to make it more accurate and move the objects in the game based on this reading. But this has it''s set backs too, like the reaction time to loop time changes slows down etc. Using two threads could be a good solution, but is a lot trickier to get it working properly due to the inherent difficulty of multithreaded programming and it might be even slower than running with one thread (I implemented single- and multithreaded versions of one of my games and noted that on single processor machines the multithreaded version was something like 1.2 times slower than the single threaded version). So these days I usually just run everything in one thread (first tick the world and the objects in it and then paint the visible objects).
-Pasi Keranen
I''ve been checking into the granularity of currentTimeMillis() under different VMs, and I don''t get consistent timing under any VM. I tested Sun''s 1.1.7B, 1.2.2, and 1.3 , all under NT 4.0.

The typical time difference I get is 10msec, but there are spots where this will increase to 30msec or more. The older VMs have more pronounced lags, sometimes as high as 100msec, in 1.1.7B. Version 1.3 is almost always 10msec, with an occasional 30msec lag. I would guess that these occur during garbage collection, and the performance difference is due in part to HotSpot''s incremental GC. I would also assume that the 50msec updates Icculus and javanerd saw were under Win95/98 VMs.

This doesn''t seriously affect my codeline, because I run under 1.3 using 50 msec updates, but I would urge all of you running under older VMs or using more frequent updates to look into the timing behavior of your production environment and research some type of antialiasing technique.

javanerd, are you saying you encountered a 120% longer execution time using multiple threads vs. a single thread on a single CPU machine? I''m curious if this was due to lock synchronization or thread context switches. I''d be interested in discussing your threading strategy with you some time.

ManaSink

This topic is closed to new replies.

Advertisement