{"id":23393098,"url":"https://github.com/reececomo/pixijs-interpolated-ticker","last_synced_at":"2025-10-29T14:31:02.074Z","repository":{"id":269217378,"uuid":"906768305","full_name":"reececomo/pixijs-interpolated-ticker","owner":"reececomo","description":"⚡️ Powerful, high-performance frame interpolation for PixiJS","archived":false,"fork":false,"pushed_at":"2025-01-16T19:40:22.000Z","size":850,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-16T20:49:40.842Z","etag":null,"topics":["decouple","fixed","gameloop","loop","physics","pixijs","timestep"],"latest_commit_sha":null,"homepage":"https://npmjs.com/pixijs-interpolated-ticker","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/reececomo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-21T21:06:03.000Z","updated_at":"2025-01-16T19:41:29.000Z","dependencies_parsed_at":"2024-12-21T21:14:59.597Z","dependency_job_id":"b2ed465e-dbfa-4b26-a6a1-ed2a98568c7a","html_url":"https://github.com/reececomo/pixijs-interpolated-ticker","commit_stats":null,"previous_names":["reececomo/pixijs-interpolated-ticker"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reececomo%2Fpixijs-interpolated-ticker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reececomo%2Fpixijs-interpolated-ticker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reececomo%2Fpixijs-interpolated-ticker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reececomo%2Fpixijs-interpolated-ticker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reececomo","download_url":"https://codeload.github.com/reececomo/pixijs-interpolated-ticker/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238837898,"owners_count":19539079,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["decouple","fixed","gameloop","loop","physics","pixijs","timestep"],"created_at":"2024-12-22T05:18:13.852Z","updated_at":"2025-10-29T14:31:02.069Z","avatar_url":"https://github.com/reececomo.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  ⚡ pixijs-interpolated-ticker\n  \u003cbr\u003e\n  \u003cbr\u003e\n  \u003cimg src=\"./hero.png\" width=50% /\u003e\n\u003cbr\u003e\n\u003c/h1\u003e\n\u003cbr\u003e\n\n\u003cp align=\"center\"\u003e\n  🏃 Independent render FPS \u0026ndash; update ticker in PixiJS\n\u003c/p\u003e\n\u003cbr\u003e\n\n\u003cp\u003e\n  \u003ca href=\"https://www.npmjs.com/package/pixijs-interpolated-ticker\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/pixijs-interpolated-ticker.svg\" alt=\"NPM version\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/reececomo/pixijs-interpolated-ticker/blob/main/LICENSE\"\u003e\u003cimg src=\"https://badgen.net/npm/license/pixijs-interpolated-ticker\" alt=\"License\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://bundlephobia.com/package/pixijs-interpolated-ticker\"\u003e\u003cimg src=\"https://badgen.net/bundlephobia/minzip/pixijs-interpolated-ticker@latest\" alt=\"Minzipped\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/reececomo/pixijs-interpolated-ticker/actions/workflows/tests.yml\"\u003e\u003cimg src=\"https://github.com/reececomo/pixijs-interpolated-ticker/actions/workflows/tests.yml/badge.svg\" alt=\"Tests\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/pixijs-interpolated-ticker\"\u003e\u003cimg src=\"https://img.shields.io/npm/dm/pixijs-interpolated-ticker.svg\" alt=\"Downloads\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003ctable\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e🔮 Simple, drop-in API\u003c/td\u003e\n\u003ctd\u003e✨ Supports PixiJS 8, 7 and 6+\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e✅ Plugin compatible\u003c/td\u003e\n\u003ctd\u003e💪 Configurable, with sensible defaults\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e🤏 Tiny (\u0026lt;2kB)\u003c/td\u003e\n\u003ctd\u003e🍃 No dependencies, tree-shakeable\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\n## Usage\n\n```ts\nconst ticker = new InterpolatedTicker({ renderer, stage });\nconst mySprite = new Sprite({ texture: Assets.get(\"cat\") });\n\nticker.start({\n    // triggered at a fixed interval\n    update: (fixedDeltaMS: number)\n    {\n        mySprite.x += 5;\n        mySprite.angle += 0.1;\n    }\n});\n```\n\n## 💿 Install\n\n```sh\nnpm i pixijs-interpolated-ticker\n```\n\n## Configuration\n\n```ts\nconst ticker = new InterpolatedTicker({ renderer, stage });\nconst mySprite = new Sprite({ texture: \"cat\" });\n\nticker.start({\n    update: (fixedDeltaMS: number)\n    {\n        // triggered at a fixed interval\n        //   (fixedMS never changes)\n    },\n\n    render: (renderDeltaMS: number, progress: number)\n    {\n        // triggered at display refresh rate\n        //   e.g. drawing additional particle effects, etc.\n    },\n});\n\n// increasing the speed affects the rate at which update(fixedDeltaMS) is\n// executed, but does not affect the value of fixedDeltaMS.\nticker.speed = 2;\n\n// limit render FPS\nticker.renderFPS = 30;\n\nticker.on(\"fps\", (fps) =\u003e\n{\n    // render FPS updated\n});\n\nticker.on(\"devicefps\", (fps) =\u003e\n{\n    // device FPS updated (independent of actual renders)\n});\n```\n\n### Lifecycle Event Hooks\n\nWhen starting the event loop, you may supply the following lifecycle event hooks\n\n| Hook | Event | Description |\n|---|---|---|\n| `update` | ***Required***\u003cbr/\u003eFixed timestep update | The core update loop of the program.\u003cbr/\u003e\u003cbr/\u003e**Note:** Changes made to containers here will be interpolated in the render loop. This may be triggered zero, one or many times in a render call (based on the target `fixedDeltaMS` and interpolated ticker `speed`).\u003cbr/\u003e\u003cbr/\u003e**Note:** Changing the interpolated ticker `speed` changes the true rate at which the update function is triggered, but `fixedDeltaMS` is not affected. |\n| `prepareRender` | *Optional*\u003cbr/\u003eA render frame is about to render. | Changes made here to containers will affect the \"end\" state for container interpolation. Triggered at the start of each render cycle, before container interpolation. |\n| `render` | *Optional **(Recommended)***\u003cbr/\u003eA render frame is about to render. | Triggered immediately before each `renderer.render()` call, after container interpolation.\u003cbr/\u003e\u003cbr/\u003e**Note:** Changes made to containers here **will** be rendered, but may be reverted to its `prepareRender` state if the container was expecting to be interpolated. |\n| `postRender` | *Optional*\u003cbr/\u003eA frame has been rendered. | Triggered after each `renderer.render()` call, after container interpolation is restored. |\n\n### Ticker Options\n\n```ts\nnew InterpolatedTicker(options: {\n    /**\n     * PixiJS renderer.\n     */\n    renderer: Renderer;\n\n    /**\n     * Stage root view.\n     */\n    stage: Container;\n\n    /**\n     * Fixed timestep interval in milliseconds.\n     *\n     * @default 16.666666666666668\n     */\n    fixedDeltaMS?: number;\n\n    /**\n     * Whether container interpolation is enabled.\n     *\n     * When enabled, container values (position, scale, rotation, alpha) are\n     * rendered at interpolated positions.\n     *\n     * @default true\n     */\n    interpolation?: boolean;\n\n    /**\n     * Container interpolation options (when enabled).\n     *\n     * @default undefined\n     */\n    interpolationOptions?: {\n        /**\n         * Maximum interpolatable change in position x/y.\n         *\n         * @default 100\n         */\n        maxDeltaPosition?: number;\n\n        /**\n         * Maximum interpolatable change in scale.\n         *\n         * @default 1\n         */\n        maxDeltaScale?: number;\n\n        /**\n         * Maximum interpolatable change in rotation.\n         *\n         * @default Math.PI/2\n         */\n        maxDeltaRotation?: number;\n\n        /**\n         * Maximum interpolatable change in alpha.\n         *\n         * @default 0.5\n         */\n        maxDeltaAlpha?: number;\n\n        /**\n         * Initial number of containers to preallocate interpolation memory for.\n         *\n         * @default 256\n         */\n        capacity?: number;\n\n        /**\n         * Maximum number of containers to allocate interpolation memory for.\n         *\n         * @default 4096\n         */\n        maxCapacity?: number;\n    },\n\n    /**\n     * The display refresh rate to target (in frames per second). Actual render\n     * rate will vary on different displays.\n     *\n     * A value of `0` means unlimited refresh rate.\n     *\n     * @default 0\n     */\n    renderFPS?: number;\n    \n    /**\n     * When `renderFPS` set, this is the maximum tolerance in milliseconds for\n     * limiting the render frame interval.\n     *\n     * @default 7.0\n     */\n    renderIntervalToleranceMS?: number;\n\n    /**\n     * Maximum frame time in milliseconds that fixed updates may accrue for\n     * before frame time stops accruing. Scaled by `speed`.\n     *\n     * @default fixedDeltaMS*3\n     */\n    maxFrameTimeMS?: number;\n\n    /**\n     * The minimum interval in milliseconds that fluctuations in FPS are reported.\n     *\n     * Listen for \"fps\" and \"devicefps\" events.\n     *\n     * @default 1000\n     */\n    fpsIntervalMS?: number;\n\n    /**\n     * The rounding level for FPS detection (e.g. 0.01).\n     *\n     * @default 1\n     */\n    fpsPrecision?: number;\n})\n```\n\n### Container Options\n\n*Configuring individual containers.*\n\n| Property | Description |\n| :----- | :------ |\n| `isInterpolated` | Set `false` to disable interpolation on this container. Defaults to `this.visible`. |\n| `hasInterpolatedChildren` | Set `false` to disable interpolation on this container's descendants. Defaults to `this.isInterpolated`. |\n\n```ts\nconst container = new Container();\n\n// skip interpolation on this container and its children\ncontainer.isInterpolated = false;\n\n// actually ...lets allow children to be interpolated anyway\ncontainer.hasInterpolatedChildren = true;\n```\n\n## Credit\n\nPixiJS InterpolatedTicker is an implementation of the ideas laid out in\n[Gafferongames' Fix Your Timestep article](https://gafferongames.com/post/fix_your_timestep/),\nand is a spiritual successor to [kittykatattack/smoothie](https://github.com/kittykatattack/smoothie).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freececomo%2Fpixijs-interpolated-ticker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freececomo%2Fpixijs-interpolated-ticker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freececomo%2Fpixijs-interpolated-ticker/lists"}