Strange timing results


AdvancedTimer at = new AdvancedTimer();
long tick = 0;
at.start();
int fps = 60;
long ticksPerFrame = (long)( AdvancedTimer.getTicksPerSecond()/(double)fps );

final int FPS_AVERAGING = 6;
int totalFPS = 0;
int [] previousFPS = new int[FPS_AVERAGING];
int fpsIndex = 0;
int paints = 0;

long lastTime;
lastTime = System.currentTimeMillis();

String fpsString = "";

while (running && game.running() && !exiting) {
      /* fps calculation */
      if (System.currentTimeMillis()-lastTime > 1000) {
            lastTime+=1000;

            totalFPS+=paints - previousFPS[fpsIndex];
            previousFPS[fpsIndex] = paints;
            fpsIndex=(fpsIndex+1)%FPS_AVERAGING;

            fpsString = Integer.toString(paints);
            paints = 0;
      }
      /* end fps calculation */

      drawing = true;
      if (visible) {
            
            Graphics2D g = (Graphics2D)strategy.getDrawGraphics();
            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
            g.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_SPEED);
            
            try { game.paintFrame(g);      }
            catch (Throwable e) {
                  err.inform(e, "game.paintFrame(g)");
                  crashed = true;
                  dispose();
            }
            
            paints++;
            
            if (DRAWS_FPS) {
                  g.setColor(Color.black);
                  g.drawString(fpsString, 0, GAME_HEIGHT);
                  
                  g.setColor(Color.white);
                  g.drawString(fpsString, 1, GAME_HEIGHT);
            }
            
            g.dispose();
            showStrategy();
            paints++;
            drawing = false;
            try {
                game.manageObjects((double)(at.getClockTicks()-tick) / AdvancedTimer.getTicksPerSecond() * fps);
            }
            catch (Throwable e) {
                err.inform(e, "manageObjects");
                crashed = true;
                  dispose();
            }
            
          at.sleepUntil(tick + ticksPerFrame);
          tick = at.getClockTicks();
      }
      else {      
      //      setCursor(Cursor.getDefaultCursor());
      //      System.out.println("not visible");
            try {
                  Thread.sleep(100);
                  tick = at.getClockTicks();
            } catch (InterruptedException e) {
                  break;
            }
      }
}

For some reason, my games are stuck running at 120 fps in all modes of display even though you can see ‘fps’ is 60. Also, I’m somewhat worried about innacuracies in the number passed to manageObjects(). When I run my game at really small resolutions, the game speed seems inconsistent. One time I’ll run it and it’ll seem like it’s running at a normal speed. I run it again and the game speed looks like it’s cut in half. Does anyone see why that might be?

I have a better idea now of where the problem is. If I comment out this line:


at.sleepUntil(tick + ticksPerFrame);

The problem removes itself. However, then I’m running my silly game at like 350fps. I still want to cap it at 60 and not have whatever error I’m having with losing accuracy. What’s the proper way to handle this?

jbanes, Abuse, help? :slight_smile:

While I havent spent the time to go over all the math here, I did notice that you have 2

paints++;

lines in the code.

As you noticed the line that does the sleeping was wrong. If the frame took 50% of the frame time, you where then waiting 100% more, so each frame was taking up 150% (at least in my example, it could be much longer) .

You need to check the current time after rendering and see if its over time. If so you keep that overage and add it to the animation on the next frame so things move the appropriate distance for the time spent. You do this already, but its in the middle of the frame’s timing. Maybe that works ok but it just looks odd to me. I do my calculation for that as the last thing in a frame, then the update comes next (which is at the top of the loop).

update(anim modifier)
render()
wait loop or call to use remaining time in current frame
calculate actual time used, create an anim modifier

If the time is under the time for one frame, you just sleep for that remaining time.

I used this as a tool for making sure my frame rate capping math worked. Try www.fraps.com it will display the frame rate you have. You can then check to see if your calculated fps matches.

Sorry Malokhan, I didn’t see this post. Did you get it fixed?

A few questions/comments:

long ticksPerFrame = (long)( AdvancedTimer.getTicksPerSecond()/(double)fps );

Why the casts? A simple “AdvancedTimer.getTicksPerSecond()/fps” would get you the correct result as a long.

if (System.currentTimeMillis()-lastTime > 1000) lastTime+=1000; 

Why combine two timing systems? You’re using GAGE, so you shouldn’t need System.currentTimeMillis().

totalFPS+=paints - previousFPS[fpsIndex]; 
previousFPS[fpsIndex] = paints; 
fpsIndex=(fpsIndex+1)%FPS_AVERAGING;

I honestly have no idea what this code is supposed to be doing, but I think Tzan is right about the multiple “paints++” call screwing up the calculation.

at.sleepUntil(tick + ticksPerFrame); 
tick = at.getClockTicks(); 

I highly recommend changing this to:

at.sleepUntil(tick + ticksPerFrame); 
tick += ticksPerFrame;

The reason is to correct for drift. If the system falls slightly behind on drawing one frame, your original code will pass that delay on throughout all proceeding renders. The corrected code, however, will allow for faster renders until the game catches up. :slight_smile:

The unnecessary casts were random shots in the dark at trying to figure out why things were off. The code you don’t understand was simply stolen from one of Abuse’s games I believe :wink: I don’t think the array is actually used hehe. I actually like the part where I don’t take on the drift. If there’s a problem that makes the game lock for a second, I don’t want the game to resume at light speed which is totally unplayable. It’s like, not only have you been screwed by your computer freezing the game, but you get doubly screwed because then the ship you were fighting is going at you triple time and you can’t even react. I’d rather the hang just stop, and then you resume normal play.

Yeah, the paints++ twice is definitely it. Thanks guys! :slight_smile:

While I was capturing the time of a slow frame and speeding up the next, I was doing it differently. I think I like this much better :slight_smile:

Looks familar, it was a little hack I put in my Balls.jar app. to even out the rate at which balls were added to the simulation.
(to avoid balls being added/removed when a small rendering speed ‘hickup’ occured.)

Code from above:


            try {
                game.manageObjects((double)(at.getClockTicks()-tick) / AdvancedTimer.getTicksPerSecond() * fps);
            }
         

Shouldnt this be: divided by fps, not mult by fps


            try {
                game.manageObjects((double)(at.getClockTicks()-tick) / (AdvancedTimer.getTicksPerSecond() / fps)  );
            }
         

If you multiply the ticks per second by 60 you get a huge number, then the result of the calculation is a very small number and doesnt modify the animation by any noticable amount. In a mostly functional game you probably wouldnt see any diference at all.


I have another question.


at.sleepUntil(tick + ticksPerFrame);  
tick += ticksPerFrame;

If we use this and the rendering doesnt catch up and is running even for a few seconds much slower, it seems that the animation modifier would be constantly getting larger, speeding up the animation not just for the amount it was over on the current frame, but also including all the previous overages, since the tick is only held to a constant pace, but the actual time is increasing at lets say 120% normal per frame.

The timing may be over by 20% per frame, after 5 frames the comparison to the constant tick rate creates a huge amount of delta time, not just the 20% for the current frame. You would be moving things now at twice (2.0) normal animation speed for just the current frame, when you only needed 120% (1.2).

So it seems to me that setting the tick to the current time (as he has) allows for the animation modifier to be correct each frame, just the plus 20%.

If there is other magic going on perhaps its accounted for.

[quote]The timing may be over by 20% per frame, after 5 frames the comparison to the constant tick rate creates a huge amount of delta time, not just the 20% for the current frame. You would be moving things now at twice (2.0) normal animation speed for just the current frame, when you only needed 120% (1.2).

So it seems to me that setting the tick to the current time (as he has) allows for the animation modifier to be correct each frame, just the plus 20%.
[/quote]
I kind of prefer it to completely catch up, myself. The way I see it, the common instances are that it falls behind for barely a few frames, you’re on a network connection where timing is important, or your computer is just too slow (in which case my algo will go full out for you). Of course, if you’d rather catch up at a rate of 120%, you can always change it to this:


long maxsleep = ticksPerFrame + (ticksPerFrame*0.2);
...
at.sleepUntil(Math.min(tick + ticksPerFrame, at.getClockTicks() + maxsleep));

I dont think you understood what I meant, I’ll take another pass at it. :slight_smile:

I agree that if it only goes slow for a few frames then this works just fine and you are fully caught up. Which is great, (I wasnt talking about slowly catching up at all). But I was trying to address a more persistant problem.

For the sake of an example:

fps cap = 100
Ticks per second = 1000
ticks per frame = 10
tick = 0

Frame 1
time to update and render frame 12
current time = 12
anim mod 1.2 (12-0) (current time - last tick / tickPerFrame )
tick=10

Frame 2
time to u/r 12
current time 24
anim mod 1.4 ( 24-10)
tick = 20

Frame 3
time to u/r 12
current time 36
anim mod 1.6 (36 -20)
tick =30

Can you see how the animation modifier gets out of control. If it only happens for a few frames its no big deal. But if a machine is under powered or there is too much stuff being drawn or alpha areas it will run slow constantly, causing the anim modifier to grow way too much. The anim mod in all the frames above should be 1.2.

Ah, I see. You were referring to the time based sprites. Sorry 'bout that. :slight_smile:

Thats ok :slight_smile:
I should have had an example before.

Just wanted to make sure I wasnt seeing things. So if I wanted animation at 50 pixels per second and work regardless of the current fps, I need my tick to be set to the current time. Which is what I was doing.

Then any sprite frame of animation would need to be determined from the elapsed time.

I just tried this for kicks, and it makes my game run so fast that I can’t even see what’s going on. Like I press accelerate, and by the next frame I’ve completely crossed the system. Interesting…

[quote]I just tried this for kicks, and it makes my game run so fast that I can’t even see what’s going on. Like I press accelerate, and by the next frame I’ve completely crossed the system. Interesting…
[/quote]
I’m guessing that one of your values is off. Make sure that sleepTime equals “timer.getTicksPerSecond()/fps” and that you don’t run the clock up before you begin rendering. If you DO run the clock, then set “ticks = timer.getClockTicks()” before entering the main loop.

I double checked that value and it’s correct. The way I run my loop is just as I showed in the code up top: render, run, sleep, repeat.