Skip to content

Commit e99f303

Browse files
committed
pixijs-interpolated-ticker v2.0.0
1 parent 069066e commit e99f303

16 files changed

+1512
-1204
lines changed

README.md

Lines changed: 187 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
<tbody>
2525
<tr>
2626
<td>🔮 Simple, drop-in API</td>
27-
<td>✨ Supports PixiJS v6, v7, v8+</td>
27+
<td>✨ Supports PixiJS 8, 7 and 6+</td>
2828
</tr>
2929
<tr>
3030
<td>✅ Plugin compatible</td>
@@ -37,159 +37,217 @@
3737
</tbody>
3838
</table>
3939

40-
## Sample Usage
40+
## Usage
4141

4242
```ts
43-
function update() {
44-
spriteA.x += 10
45-
spriteB.rotation -= Math.PI * 0.125
46-
}
47-
48-
const loop = new InterpolatedTicker({ app, update })
49-
50-
// run @ 24Hz:
51-
loop.updateIntervalMs = 1000 / 24
52-
loop.start()
43+
const ticker = new InterpolatedTicker({ renderer, stage });
44+
const mySprite = new Sprite({ texture: "cat" });
45+
46+
ticker.start({
47+
// triggered at a fixed timestep
48+
update: (fixedDeltaMs: number)
49+
{
50+
mySprite.position.x += 10;
51+
mySprite.rotation += 0.1;
52+
}
53+
});
5354
```
5455

55-
## Getting Started
56-
57-
### 💿 Install
56+
## 💿 Install
5857

5958
```sh
6059
npm i pixijs-interpolated-ticker
6160
```
6261

63-
### Overview
64-
65-
- The **update()** function records **keyframes**
66-
- The ticker renders frames to the framebuffer using interpolated values for `x`, `y`, `scale`, `rotation`, and `alpha`
67-
68-
## Advanced Configuration
69-
70-
### Ticker Options
71-
72-
*Configuring your interpolation ticker.*
62+
## Configuration
7363

7464
```ts
75-
const mainLoop = new InterpolationTicker({
76-
app: myApplication,
77-
78-
// the update loop function, used as keyframes
79-
update: () => {},
80-
81-
// enable/disable frame interpolation (default = true)
82-
interpolation: true,
83-
84-
// how frequently to trigger update loop (default = 1000/60)
85-
updateIntervalMs: 1000/30,
86-
87-
// set a maximum render FPS, -1 is unlimited (default = -1)
88-
maxRenderFPS: 60,
89-
90-
// maximum change in alpha to animate (default = 0.5):
91-
autoLimitAlpha: 0.1,
92-
93-
// maximum change in x or y to animate (default = 100):
94-
autoLimitPosition: 250,
95-
96-
// maximum change in rotation to animate (default = Math.PI / 4):
97-
autoLimitRotation: Math.PI,
98-
99-
// maximum change in scale to animate (default = 1.0):
100-
autoLimitScale: 1.5,
101-
102-
// hook triggered at the start of a render, immediately
103-
// following any update frames that have been processed.
104-
// containers' values are their latest keyframe values.
105-
preRender: ( deltaTimeMs ) => {},
106-
107-
// hook triggered during a render, immediately before
108-
// writing to the framebuffer. containers' values are
109-
// their interpolated values.
110-
onRender: ( deltaTimeMs ) => {},
111-
112-
// hook triggered at the end of a render. containers'
113-
// values are their latest keyframe values.
114-
postRender: ( deltaTimeMs ) => {},
115-
116-
// hook triggered at the start of each evaluation cycle, before
117-
// any update or render frames are processed.
118-
evalStart: ( startTime ) => {},
119-
120-
// hook triggered at the end of each evaluation cycle, after all
121-
// update and render frames have been processed.
122-
evalEnd = ( startTime ) => {},
123-
124-
// initial number of containers to reserve memory in the internal
125-
// buffer for. note: the internal buffer will resize automatically
126-
// when it is full. (default = 500):
127-
initialCapacity: 2500,
128-
})
65+
const ticker = new InterpolatedTicker({ renderer, stage });
66+
const mySprite = new Sprite({ texture: "cat" });
67+
68+
ticker.start({
69+
update: (fixedDeltaMS: number)
70+
{
71+
// triggered at a fixed interval
72+
// fixedDeltaMS never changes
73+
},
74+
75+
render: (renderDeltaMs: number, progress: number)
76+
{
77+
// triggered at display refresh rate
78+
// e.g. drawing additional particle effects, etc.
79+
},
80+
81+
renderPrepare: (renderDeltaMS: number)
82+
{
83+
// triggered at display refresh rate
84+
// prior to container interpolation
85+
},
86+
});
87+
88+
// increasing the speed affects the rate at which update(fixedDeltaMS) is
89+
// executed, but does not affect the value of fixedDeltaMS.
90+
ticker.speed = 2;
91+
92+
// limit render FPS
93+
ticker.renderFPS = 30;
94+
95+
ticker.on("fps", (fps) =>
96+
{
97+
// render FPS updated
98+
});
99+
100+
ticker.on("devicefps", (fps) =>
101+
{
102+
// device FPS updated (independent of actual renders)
103+
});
129104
```
130105

131-
and other additional non-constructor values:
106+
### Ticker Options
132107

133108
```ts
134-
const mainLoop = new InterpolatedTicker({ app })
135-
136-
// run the update loop at 125% speed:
137-
mainLoop.speed = 1.25
138-
139-
// restrict render skips - if rendering is interrupted for any
140-
// reason - e.g. the window loses focus - then this will
141-
// limit the maximum number of "catch-up" frames (default = 10):
142-
mainLoop.maxUpdatesPerRender = 10
143-
144-
// set custom opt-in or opt-out logic for container interpolation.
145-
// when `container.interpolation` is not set yet, this function is
146-
// evaluated once to hydrate that property.
147-
//
148-
// you could set this to () => false to opt-out by default, and then
149-
// manually set container.interpolation = true in the containers you
150-
// want to interpolate.
151-
//
152-
// (default: () => true)
153-
mainLoop.getDefaultInterpolation = ( container ): boolean => {
154-
return !(container instanceof Mesh)
155-
}
109+
new InterpolatedTicker({
110+
/**
111+
* PixiJS renderer.
112+
*/
113+
renderer: Renderer;
114+
115+
/**
116+
* Stage root view.
117+
*/
118+
stage: Container;
119+
120+
/**
121+
* Fixed timestep interval in milliseconds.
122+
*
123+
* @default 16.666666666666668
124+
*/
125+
fixedDeltaMs?: number;
126+
127+
/**
128+
* Whether container interpolation is enabled.
129+
*
130+
* When enabled, container values (position, scale, rotation, alpha) are
131+
* rendered at interpolated positions.
132+
*
133+
* @default true
134+
*/
135+
interpolation?: boolean;
136+
137+
/**
138+
* Container interpolation options (when enabled).
139+
*
140+
* @default undefined
141+
*/
142+
interpolationOptions?: {
143+
/**
144+
* Maximum interpolatable change in position x/y.
145+
*
146+
* @default 100
147+
*/
148+
maxDeltaPosition?: number;
149+
150+
/**
151+
* Maximum interpolatable change in scale.
152+
*
153+
* @default 1
154+
*/
155+
maxDeltaScale?: number;
156+
157+
/**
158+
* Maximum interpolatable change in rotation.
159+
*
160+
* @default Math.PI/2
161+
*/
162+
maxDeltaRotation?: number;
163+
164+
/**
165+
* Maximum interpolatable change in alpha.
166+
*
167+
* @default 0.5
168+
*/
169+
maxDeltaAlpha?: number;
170+
171+
/**
172+
* Initial number of containers to preallocate interpolation memory for.
173+
*
174+
* @default 256
175+
*/
176+
capacity?: number;
177+
178+
/**
179+
* Maximum number of containers to allocate interpolation memory for.
180+
*
181+
* @default 4096
182+
*/
183+
maxCapacity?: number;
184+
},
185+
186+
/**
187+
* The display refresh rate to target (in frames per second). Actual render
188+
* rate will vary on different displays.
189+
*
190+
* A value of `0` means unlimited refresh rate.
191+
*
192+
* @default 0
193+
*/
194+
renderFPS?: number;
195+
196+
/**
197+
* When `renderFPS` set, this is the maximum tolerance in milliseconds for
198+
* limiting the render frame interval.
199+
*
200+
* @default 7.0
201+
*/
202+
renderIntervalToleranceMS?: number;
203+
204+
/**
205+
* Maximum frame time in milliseconds that fixed updates may accrue for
206+
* before frame time stops accruing. Scaled by `speed`.
207+
*
208+
* @default fixedDeltaMs*3
209+
*/
210+
maxFrameTimeMs?: number;
211+
212+
/**
213+
* The minimum interval in milliseconds that fluctuations in FPS are reported.
214+
*
215+
* Listen for "fps" and "devicefps" events.
216+
*
217+
* @default 1000
218+
*/
219+
fpsIntervalMs?: number;
220+
221+
/**
222+
* The rounding level for FPS detection (e.g. 0.01).
223+
*
224+
* @default 1
225+
*/
226+
fpsPrecision?: number;
227+
})
156228
```
157229

158230
### Container Options
159231

160232
*Configuring individual containers.*
161233

162-
Containers are granted _optional_ properties to make it easy to configure advanced interpolation.
163-
164-
Interpolation is opt-out for stage containers, and disabling interpolation for a container will also disable it for all descendants.
165-
166234
| Property | Description |
167235
| :----- | :------ |
168-
| `interpolation` | Whether interpolation is explicitly enabled or disabled for this container. The default behavior for all containers is `true`. |
169-
| `interpolatedChildren` | An array of child containers to include in interpolation. When not set, `children` is used. |
170-
| `interpolationWraparound` | If set, position will smoothly wraparound the given ranges. |
236+
| `isInterpolated` | Set `false` to disable interpolation on this container. Defaults to `this.visible`. |
237+
| `hasInterpolatedChildren` | Set `false` to disable interpolation on this container's descendants. Defaults to `this.isInterpolated`. |
171238

172239
```ts
173-
// disable interpolation for a container
174-
// (and all of its descendants):
175-
const sprite = new Sprite()
176-
sprite.interpolation = false
177-
178-
// allow a container's position to wraparound smoothly:
179-
const background = new Sprite()
180-
background.interpolationWraparound = {
181-
xRange: 1000,
182-
yRange: 2000
183-
}
184-
185-
// explicitly set which children may be interpolated
186-
const parent = new Container()
187-
const childA = new Container()
188-
const childB = new Container()
189-
parent.addChild( childA, childB )
190-
parent.interpolatedChildren = [ childB ]
240+
const container = new Container();
241+
242+
// skip interpolation on this container and its children
243+
container.isInterpolated = false;
244+
245+
// actually ...lets allow children to be interpolated anyway
246+
container.hasInterpolatedChildren = true;
191247
```
192248

193-
## Credits
249+
## Credit
194250

195-
PixiJS InterpolatedTicker is a spiritual successor to [kittykatattack/smoothie](https://github.com/kittykatattack/smoothie).
251+
PixiJS InterpolatedTicker is an implementation of the ideas laid out in
252+
[Gafferongames' Fix Your Timestep article](https://gafferongames.com/post/fix_your_timestep/),
253+
and is a spiritual successor to [kittykatattack/smoothie](https://github.com/kittykatattack/smoothie).

0 commit comments

Comments
 (0)