I have seen bits of code of different timming loops and they all have the tick variables. I was wondering whats the theory behind these ticks? I wish to do a few things like update ai, frame independed movement, and fps display and know all these things require tracking the ticks inside a timming loop. But I am a bit confused how are variables like curretTick lastTick are used and what do they mean.
Kommi,
I’m not entirely sure which code you’ve seen, but I don’t think it matters.
There’s a timer that runs during the game loop. This timer may or may not be at the rate you want, or (as in the case of the Windows high performance timer which is used by GAGE and my own library) runs MUCH faster than you need. The Windows runs in microseconds, whereas most platforms will give you a one millisecond resolution on System.getCurrentTimeMillis().
Because the timer may not be completely divisible with your loop, you might encounter “drift” where you lose a few milliseconds here or there. So most loops have what’s called a “delta” which is the time between the current “tick” of the clock, and the previous one, so that you can lengthen or shorten the next “tick.”
So what are these ticks? Well, I’m assuming you’re not attempting 1000fps, which would mean 1 millisecond per frame. Rather, let’s say like I do that you have eight frames of animation and you want to display them in one second. This gives you 125 milliseconds for each update, and therefore you have 8 “ticks” per second.
Naturally the timer doesn’t care what my game ticks are; it runs at its speed. So in truth I’m clocking some 140000 ticks between frames, and if I adjust for drift I have to know how much longer or shorter to sleep for to keep to that 140000 ticks per frame (the reason it isn’t 125000 ticks is that the windows timer is actually running at slightly higher than 1 million ticks per second. On a Mac, it’s exactly 1 tick per millisecond, so I would have 125 ticks between frames, and I would adjust accordingly).
I know this might sound a bit convoluted, so feel free to ask for clarification.
I have a native timer implementation with a granularity of 25.6574… microseconds. This is very accurate but since its not my code I am not sure how much access I have to the timer. I will post my code later in the day and maybe someone will help me write a tick implementation. Hey GergisKhan, I was wondering whats the granularity of the GAGE implementation?
[quote]I was wondering whats the granularity of the GAGE implementation?
[/quote]
It varies from system to system, but the GAGE timer guarantees at least 1 ms resolution on all systems. On Windows, it does far, far better. Probably the same resolution as your timer considering that it uses the standard Windows Hi-Res timer.
OK so let me see if I got it:
If I have a timer with aprox 1000 ticks per second
then if I want 60 fps I have to redraw every 1000/60 = 16.6 ticks
If I want an 8 fps char animation I have to update it every 1000/8 = 125 ticks
and if my char moves 1 pix at a time and I want him to move 20 pix/sec then I have to update his location every 50 ticks. I would also do collision detection and check for keyboard at this interval.
Did I get the idea right? Or am I missing something?
I have decided to switch over to the GAGE timer implementation.
Question 2
Can someone please remind what to do with the file I got from http://java.dnsalias.com/ for the hires timer.
I cant remeber wether I have to unzip it or just set a class path to it or what. Can someone please describe the setup and any import statements that I will have to put in my code. Thanx
You’ve got it. Don’t worry too much about the .6 ticks tho. They usually get rounded out of the equation thanks to VSyncs.
AS for how to use the timer, there are two files to worry about. “timer.dll” must always be in the directory you launch your app from. If you see an exception on startup and your app seems to run jerky, you probably don’t have it in the right place. Timer.dll can either be referenced in the classpath (usually using the path in an executable JAR file) or it can be extracted and put in your own JAR file.
Thanx for the reply but one more newbie question. If I have your file then where do I unzip it to and how do I set the classpath for it? Also I take it that I just do AdvancedTimer timer = new AdvancedTimer(); in my code without importing anything?
You need to import com.java.dnsalias.timer.*; whenever you instantiate a timer i think. I decided not to fiddle with the .dll file yet, instead I took the com directory from the bin folder in the zip archive and dumped it into the same main directory of my project. Then I would just refer to the AdvancedTimer class just like any of my own classes in my game.
I take it that the ticks per second depend on the cpu speed of the machine. I am getting 3,500,000 ticks per second on my Athlon XP1800 WIN2K using the GAGE timer.
Question: If I want to setup the delta ticks mechanism I would call getClockTicks() twice, once before
sleepUntil(), once after, and then take the difference right?
Delta of what? For the equations you have above (1000/60, etc.) you simply need to replace 1000 with timer.getTicksPerSecond(). Thus:
long ticksPerFrame = timer.getTicksPerSecond()/60;
Yeah its fine if I want the frame rate to be 60 fps then
sleepTime = timer.getTicksPerSecond()/60;
.
.
dostuff();
timer.sleepUntil(ticks+sleepTime);
ticks += sleepTime;
But what if I want an animation to update its frame once every timer.getTicksPerSecond()/8 which is 8fps
then how would I implement that?
Kommi,
I believe there are in fact two frame rates involved here. If you are using BufferStrategy, I don’t think you need worry about one of them.
There are in fact two different rates going here. In fullscreen mode using BufferStrategy, the screen will refresh itself at whatever the monitor refresh rate is. If you are set to 60Hz, then the screen will display 60 frames per second.
This is different than your own refreshes, which, if I read you correctly, indicates you have eight frames of animation to display.
Simply ignore what the BufferStrategy is doing. Refresh at ticksPerSecond()/8 and the rest of the frames will simply use whatever is in the buffer at that time. Remember, you’re not updating the screen itself, you’re updating the buffer. The screen refresh uses whatver buffer contents are available.
An additional thought: you may wish to time your animation loop. To do this, I modified the AdvancedTimer so that getTime() is now public.
int start = timer.getTime();
render();
updateSprites();
int timeOfFrame = timer.getTime() - start;
timer.sleep( ( timer.getTicksPerSecond() / 8 ) - timeOfFrame );
This fragment ensures that I’m sleeping for the exact amount of an 8 frame refresh, and stablizes the loop somewhat. You need to assure, however, that you can complete all operations within 125 milliseconds, or else this idea doesn’t work.
I’m checking out the gage timer for our game and I get a unsatisfied link error: getResolution
I’m calling System.loadLibrary(“timer”); before hand and I get no error with this call so it is loading the timer.dll-I know I don’t have to do this because its done inside the WindowsTimer class, its there just for testing.
I’m also compiling the AdvanceTimer, NativeTimer and WindowsTimer java files with my own files so I don’t have to import anything. I changed the Package to my package name as well, everything compiles fine, just getting the runtime error.
Changing the package names will break the JNI interface. The naming of the C functions created is based on the package name of the class.
Kev
Ok good point, but still having problems with the same error, when I just import that timer.jar file.
I can compile and I don’t throw an error when it loads in the dll, I have access to all the timer classes but still when running I get the unsatisfied link error: getResolution when asking for the GAME_TIMER.getTicksPerSecond()/60;
Any suggestions?
I dont think I made my question clear in the last post. So here is the situation. Lets say I am updating 3 diffrent things:
- The whats drawn to the screen
- The char location
- AI
Now lets say I have a 1000 ticks per second (in theory of course).
- If I want 60ps then I have to update the draw() once every 1000/60 = 16 ticks.
- If I want the char location and other things pertaining to it at 20 times a second then that gets updated every 50 ticks. The character also has an 8fps animation that gets updated once every 125 ticks.
- Now lets say the AI gets updated once every 300 ticks.
My problem is that I am not sure as to how to manage these updates. According to the above, one second of game time gets the following calls:
0,1,2,3,4,…16 draw(),17,18,…32draw()…48 draw(),49,50 updateChar(),…
So I have to setup a mechanism that calls my methods at certain time intervals. to make sure that the timer sleeps once every (1000/60) ticks and the game loop calls updateChar() once every(1000/20) ticks, and calls AI() once every (1000/3) ticks. My prob is that I am not sure how to implement this. At first I thought I would need a delta ticks to keep track of how many ticks passed and then call certain methods at a certain value of delta ticks. But now Im not sure.
This problem is similar to trying to implement frame independent movement. That implementatiomn uses delta ticks so I am guessing that I need it here as well.
I hope I my post is not confusing enough
[quote] An additional thought: you may wish to time your animation loop. To do this, I modified the AdvancedTimer so that getTime() is now public.
[/quote]
Why in the world did you do that? Is there something wrong with clock ticks?
[quote]Ok good point, but still having problems with the same error, when I just import that timer.jar file.
[/quote]
- Do not call System.loadLibrary. The timer calls it on its own. A second call will merely result in an exception.
- Make sure that timer.dll is either in the same directory as you are running the code from, or that it’s in the system PATH (e.g. c:\winnt\system32)
Off the top of my head algo, assuming 1000/sec:
long nextDraw = timer.getClockTicks()+16;
long nextChar = timer.getClockTicks()+50;
long nextAI = timer.getClockTicks()+300;
while(true)
{
if(nextDraw < timer.getClockTicks())
{
drawStuff();
nextDraw = nextDraw+16;
}
if(nextChar < timer.getClockTicks())
{
doCharacterStuff();
nextChar = nextChar+50;
}
if(nextAI < timer.getClockTicks())
{
doAIStuff();
nextAI = nextAI+300;
}
}
Ok, gotta jet. Busy, busy, busy. That’s what this most recent DD release is…
EDIT: Fixed a goof-up in the if statements of my example code.
Wow thats pretty cool. I have tried your code jbanes, and naturally it works Its interesting how there is no timer.sleep involved. Although the effect is the same as with a sleep. I take it that calling methods at certain amounts of ticks without a sleep method is a much better way of doing the game loop, as it allows for more control. I was wondering if this is how it is usually done?
This would cause problems if you were using more than one thread tho, might slow down AWT thread for instance? Is that right?
Kev