Archived

This topic is now archived and is closed to further replies.

[java] Keeping constant framerate

This topic is 6349 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
I think I read somewhere that Timer objects don''t run in a seperate thread, that they were intended for Swing objects which need to be updated but aren''t syncronized. Can someone verify if this is true?

The way my games work is that I grab the current system time at the beginning of the thread, do the hard parts, then grab the time again. Figure out how long it took, and sleep whatever time is left. When I just used a static Thread.sleep(40), the game sped up and slowed down depending on how much work was going on. Sure there are still some bumps in the framerate here and there, but for the most part, it works fine. It is really only obvious when doing scrolling. And I''m doing 2D games so tying the animation to the framerate isn''t a problem. It is almost required.

Share this post


Link to post
Share on other sites
quote:
Original post by Squidi

I think I read somewhere that Timer objects don''t run in a seperate thread, that they were intended for Swing objects which need to be updated but aren''t syncronized. Can someone verify if this is true?




javax.swing.Timer uses a runnable inner class, DoPostEvent, and a singleton instance of TimerQueue, which has its own thread, so Timer objects "run" in *a* seperate thread. To be specific, one DoPostEvent instance runs in the TimerQueue thread for each started instance of Timer.

When you say "intended for Swing objects which need to be updated but aren''t syncronized", what exactly do you mean? I can verify that Timers are useful for changing the state of visual components without involving their painting methods, but that may not be what you were asking. The words "update" and "synchronized" can be a bit ambiguous in this discussion.

ManaSink

Share this post


Link to post
Share on other sites
quote:
Original post by ManaSink
I would also assume that the 50msec updates Icculus and javanerd saw were under Win95/98 VMs.

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.


The 50msec updates occured under WinNT 4.0 with JDK 1.2 and Microsoft Java SDK 3.0. Actually the update rate fluctuated a bit around 30-50msec, but mostly staying in the 50msec range.

The 120% increase in execution times (showing up as less frames per second outputted) were propably caused by context switching. As I did have a very light synchronization strategy. The application I was mentioning is an Asteroid emulator that runs the original Asteroid game within a virtual arcade HW. I made use of the fact that the original game had a separate processor for the graphics drawing and thus had to have implemented some kind of synchronization. So I just synchronized the access to the one flag that then triggers the execution of paint process.

I''d be happy to discuss this thing over with you if you like.

Share this post


Link to post
Share on other sites
ManaSink:

An example. I was just working on a game test that created a thread for the game logic. It called repaint() to draw the offscreen buffer on the screen, but this was handled by the default thread the applet starts up in. Because there was no synchronization attempts on my part, the applet thread would just paint the buffer whenever it felt like, no matter what state the buffer was in. This led to a lot of flickering and nastiness. I could minimize the time it took to draw stuff to the screen, as well as either skip bad frames or wait on them (both came up with bad results).

Next, I tried using a Timer instead of a seperate Thread object. After repaint is called, the same default applet thread handles the painting...thus no flickering (though the framerate did stutter every dozen frames or so - don''t think that can be helped).

The difference is that Threads work by operating everything from their run() function. A Timer passes an ActionEvent to the applet, and lets the default applet event thread handle it. So a Thread allows you to run stuff at the same time, whereas a Timer will just send action events at a regular interval. Pretty smart thinking.

It is written in "Java Foundation Class in a Nutshell":

"These operations can also be performed with threads, of course, but since Swing is not designed for thread safety, it is usually more convenient to use a Timer."

Anyway, I was a little confused, but I was on the right track. Now I know...and knowing is half the battle.

Share this post


Link to post
Share on other sites