3
\$\begingroup\$

Is there a good (accepted) method for "fixing" the cycle time within an HTML5 canvas game implementation?

The game that I have been working on runs far quicker in Google Chrome than in other browsers such as Firefox, Opera, or IE9. To be honest, it kind of reminds me of running a game from the early 90's on a brand new machine.

\$\endgroup\$
1

3 Answers 3

4
\$\begingroup\$

It sounds like you're looking for framerate-independent animation. If you're using a faster machine and your animations hang around for a certain number of frames, they'll appear to be moving faster. If your animations however are set to last for a certain number of milliseconds (framerate independent) then everything should appear the same on each machine.

There are exceptions to this, such as if the machine is very slow and the cycle time is longer than the expected duration of more than one frame in the animation, you may need to skip frames which can make things look not so nice.

Some searching revealed this example. Of note is the prototype for the Animation class, where the update function takes a time delta since the previous frame.

This framerate independent approach should be applied to all other concepts in the game as well such as character movement. Consider your standard walking speed to be in terms of pixels (at the current resolution) per second rather than pixels per frame.

\$\endgroup\$
3
  • \$\begingroup\$ +1000 for the link...that looks like exactly what i need \$\endgroup\$
    – erik
    Commented Aug 26, 2011 at 15:41
  • \$\begingroup\$ The other common option in game development is to limit frameframe. This has the effect of the game never running faster than your intended speed, but on slower machines, it can run slower than your intended speed. Sometimes that is better than skipping frames. Regardless, be careful not to mix the two techniques. That is a common mistake made by those developing games in Flash, and can make a game either far easier, or impossible if the game "lags". \$\endgroup\$ Commented Aug 26, 2011 at 17:29
  • 1
    \$\begingroup\$ @Kevin good point, and for the sake of completeness I'd like to add that if somebody is using setTimeout or setInterval for their timing, the functions don't guarantee to execute at the time you want and can be a few milliseconds out. It's best to record the time of the last frame and check the difference when your update function gets executed, regardless of how many milliseconds you asked to sleep for. A good article can be found here. \$\endgroup\$ Commented Aug 26, 2011 at 17:55
2
\$\begingroup\$

For many games I recommend implementing game logic that updates in fixed time intervals. When updating your game, measure how much time has elapsed and then run as many game ticks as needed to update your game state to the current time.

pseudo code:

var gameSimulatedTime = 0;
var tickTime = 1000/60; // game logic runs at 60 ticks per second
update() {
    var newWallTime = (new Date()).getTime();
    var deltaTime = newWallTime - gameSimulatedTime;
    if (deltaTime > 1000) // If over 1 second has elapsed, ignore and only update 1 frame.
        gameSimulatedTime = newWallTime-1;

    while (gameSimulatedTime < newWallTime) {
      gameSimulatedTime += tickTime;
      updateGameStateByOneTick();
    }
}

Notes:

  • If you browse away and come back, and or have very low frame rate, the logic squelches the huge update and just updates one frame.
  • Game time is never lost.. If wall time has progressed for 1.5 ticks worth of time and then another 1.5 ticks worth the logic will correctly update the game for 3 ticks.

Pros:

  • Even at low frame rates the game will update deterministically
  • Some game logic is easier to implement in a simple "one step at a time" manner, instead of dealing with e.g. 17.490823ms of elapsed time.

Cons:

  • Game logic may be run many times over each visual frame. If computation is expensive (e.g. A* pathfinding) it may be preferable to update only once and provide the amount of time that should be accounted for.
  • The discrete updates can cause beat patterns if e.g. the visual update is running at 45fps and game logic at 60fps. The game logic would update one tick, two ticks, one tick, two ticks, ... for each visual frame. In practice this often isn't that perceptible. Based on how expensive your update logic is, you can make the tickTime very small and greatly reduce this, e.g. tickTime = 1000/120 or even 1000/240.

If these Cons are real issues for your game, then move to more complicated update methods.

\$\endgroup\$
0
\$\begingroup\$

In: http://github.com/j03m/trafficcone (an html5 game engine I wrote) the way I approached was to use requestAnimationFrame but then also allow each sprite frame to have a speed attached to it in milliseconds. So, what you can do there is defined frame by frame the speed (so, if certain movements were to seem explosive and then slow down you can do that as well). From there, the engine tracks the last time the frame changed and handles it accordingly and uniformly.

Docs are still a little rough, but there are some usable/runnable examples. The Sprite.js and Frame.js classes might serve as good examples.

One thing I didn't do was apply this to movement :-/ where you have the same issue. Things flying around the screen on chrome but lagging on iOS. Will add that in next release.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .