npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

physics-timer

v1.0.1

Published

Utility to provide stable game physics in the presence of an undesired / unstable frame rate

Downloads

4

Readme

PhysicsTimer

A game helper to provide consistent, stable physics system behavior across varying or mismatched framerates. More generally, you can use this library to make a particular event happen at a specific average rate when it needs to run as part of a cycle that runs at a different and/or unstable rate.

Features:

  • Game engine agnostic
  • Physics engine agnostic
  • Graceful handling for varying framerates / temporary slowdowns
  • Prevents large time jumps when game / system is temporarily paused
  • Stabilization algorithm prevents jitter due to timer drift

Purpose

The Problem

Physics engines simulate the world in discete steps. Games update their graphics in discrete steps. An obvious (and common) approach, then, is to take one physics step per game update. This falls apart, however, when the game update does not run at a perfectly stable rate, or runs faster or slower than the game designers intended.

To make the game always run at the same perceived speed, we want to make the physics engine handle varying framerates.

Bad Solutions

One solution is to ignore the problem. The Phaser game engine, for example, ties itself by default to the screen refresh rate, assumes that rate is 60Hz, and then simply lets games run at double speed when the browser and monitor happen to support 120Hz, or lets games slow down if the system is slow.

Most physics engines allow a custom timestep. Another solution, then, is to measure actual time elapsed since the previous update, and ask the physics engine to take steps of variable size. The problem with this approach is that in almost all physics engines, running the same simulation in different-sized times steps produces different results. Thus if you take this approach, the behavior of the game — not the appearance, not the smoothness, but the actual game behavior — will depend on the system performance. This can produce nonsensical results such as “the player can jump higher on slower systems.”

A third solution people often come up with is to try to make the physics system run concurrently with the rendering. Using this to achieve truly independent timing requires parallel execution, and Javascript does not support parallelism. (Even in languages that do, it is tricky to make this solution work well. Physics and rendering share a lot of data: the rendering code needs to read the positions of physics bodies. The resulting need for synchronization between physics and rendering thus makes it difficult for the timing of the two to be independent.)

A Good Solution

  • Run the physics inside the game’s update cycle, no concurrency.
  • Always advance the physics simulation by the same fixed timestep.
  • Vary the number of physics steps per update based on the observed speed of the update cycle.

So, for example, if you want a 60Hz physics update cycle:

| game update fps | resulting steps per update | |-----------------|----------------------------| | 60 | 1 1 1 1 … | | 30 | 2 2 2 2 … | | 120 | 1 0 1 0 … | | 90 | 1 1 0 1 1 0 … | | unstable | 1 0 1 2 1 …??… |

Those last two scenarios will not look perfectly smooth, but they will at least create consistent speed.

This library achieves these different step-per-update patterns — even when physics rate and update rate are not tidy multiples of each other, and even when the update rate is unstable. This library also provides a simple algorithm that helps prevent jitter when the actual update rate is very close to but not exactly equal to the desired rate.

Usage

In your game / scene setup, create an instance of PhysicsTimer, providing a callback that increases the physics system by a single fixed step:

const physicsTimer = new PhysicsTimer(() => physicsSystem.step())
// (And disable game system’s automatic physics stepping if necessary)

There are a few options you can change when creating a PhysicsTimer (see source docs for details):

new PhysicsTimer(() => physicsSystem.step(), {
    timePerStep: 1000 / 120,  // 120 physics updates per second (default: 60)
    maxTimePerUpdate: 500,    // Allow up to a 500ms time jump per update (default: 100)
    stabilizationFactor: 0.5  // Aggressive stabilization (default: 0.1)
})

Then in your update / animation / rendering cycle, call the PhysicsTimer’s update method:

physicsTimer.update()

By default, PhysicsTimer uses the system clock (using the high-resolution Javascript time API if available, and falling back to old APIs if necessary). If your game system already provides a time delta, you can pass it:

physicsTimer.update(dt)

Here is a more complete example of how to integrate this library with Matter physics engine in the Phaser game platform:

import PhysicsTimer from 'physics-timer'

export default class ThrillingGameScene extends Phaser.Scene {
    private physicsTimer: PhysicsTimer

    create() {
        this.matter.world.autoUpdate = false  // ⚠️ Note we have to tell Phaser not to update physics for us
        this.physicsTimer = new PhysicsTimer(() => this.matter.world.step())
        ...
    }

    update(t: number, dt: number) {
        this.physicsTimer.update()  // You can pass dt to use Phaser's timer instead,
                                    // but I find using the system clock is smoother
        ...
    }
}

Acknowledgements

Thanks to Cameron Nokes for the helpful guide on publishing Typescript npm packages. And thanks to my students for building cool stuff and giving me nice problems to help solve.