🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@armniko/ticker

Package Overview
Dependencies
Maintainers
0
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@armniko/ticker - npm Package Compare versions

Comparing version
1.1.0
to
2.0.0
+17
dist/fps/fps.d.ts
import { Time } from '../interfaces/time.interface';
export declare class Fps {
private _minFps?;
private _currentFps;
private _lastChecks;
private _calculateFpsEachMs;
private _msSinceLastCalculation;
private _lowFpsInRow;
private _lowFpsCallback?;
currentFps(): number;
calculate(time: Time): void;
onLowFps(callback: () => void): void;
setMinFps(minFps: number): this;
private collectFps;
private calculateAverageFps;
private checkAndNotifyLowFps;
}
import { Time } from './time.interface';
export interface DrawQueueItem {
callback: (time: Time) => void;
}
import { Time } from './time.interface';
export interface LogicQueueItem {
callback: (time: Time) => void;
}
export interface LowFpsQueueItem {
callback: (fps: number) => void;
}
export interface TickerTaskId {
index: number;
type: 'draw' | 'logic' | 'low-fps';
}
export interface Time {
delta: number;
deltaMs: number;
}
import { Ticker } from './ticker';
export declare class TickerMock extends Ticker {
private _isStarted;
start(): void;
stop(): void;
isStarted(): boolean;
fps(): number;
msBetweenTicks(): number;
ticksMissed(): number;
simulateLogicTick(): void;
simulateDrawTick(): void;
simulateLowFps(): void;
}
import { TickerOptions } from '../interfaces/ticker-options.interface';
import { TickerTaskId } from '../interfaces/ticker-task-id.interface';
import { DrawQueueItem } from '../interfaces/draw-queue-item.interface';
import { LogicQueueItem } from '../interfaces/logic-queue-item.interface';
import { LowFpsQueueItem } from '../interfaces/low-fps-queue-item.interface';
export declare class Ticker {
private readonly _fps;
private readonly _drawQueue;
private readonly _logicQueue;
private readonly _lowFpsQueue;
private _maxFps;
private _expectedFps;
private _time;
private _lastTimestamp;
private _logicTicksAccumulatedMs;
private _requestFrameId?;
constructor(options?: TickerOptions);
start(): void;
stop(): void;
isStarted(): boolean;
setFps(options: {
min?: number;
max?: number;
expected?: number;
}): this;
addDrawTask(callback: DrawQueueItem['callback']): TickerTaskId;
addLogicTask(callback: LogicQueueItem['callback']): TickerTaskId;
addLowFpsTask(callback: LowFpsQueueItem['callback']): TickerTaskId;
remove(taskId: TickerTaskId): void;
fps(): number;
/**
* @deprecated Use `time.deltaMs` provided in draw/logic task callbacks instead.
*/
msBetweenTicks(): number;
/**
* @deprecated Use `time.deltaMs` provided in draw/logic task callbacks instead.
*/
ticksMissed(): number;
private loop;
private runQueue;
private runLogicQueue;
private runDrawQueue;
private compensatedMaxFps;
}
+4
-1

@@ -1,1 +0,4 @@

export * from './libraries/ticker';
export * from './ticker/ticker';
export * from './ticker/ticker-mock';
export * from './interfaces/time.interface';
export * from './interfaces/ticker-task-id.interface';
+1
-1

@@ -1,1 +0,1 @@

var s={d:(t,e)=>{for(var i in e)s.o(e,i)&&!s.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:e[i]})},o:(s,t)=>Object.prototype.hasOwnProperty.call(s,t)},t={};s.d(t,{R:()=>a});class e{_minFps;_currentFps=60;_lastChecks=[];_calculateFpsEachMs=2e3;_msSinceLastCalculation=0;_lowFpsInRow=0;_lowFpsCallback;currentFps(){return this._currentFps}calculate(s){this.collectFps(s),this._msSinceLastCalculation+=s,this._msSinceLastCalculation>=this._calculateFpsEachMs&&(this._msSinceLastCalculation=0,this.calculateAverageFps(),this.checkAndNotifyLowFps())}onLowFps(s,t){this._minFps=s,this._lowFpsCallback=t}collectFps(s){this._lastChecks.push(Math.round(1e3/s))}calculateAverageFps(){const s=this._lastChecks.reduce(((s,t)=>s+t),0);this._currentFps=Math.round(s/this._lastChecks.length),this._lastChecks=[]}checkAndNotifyLowFps(){this._minFps&&this._currentFps<this._minFps&&(this._lowFpsInRow++,5===this._lowFpsInRow&&(this._lowFpsInRow=0,this._lowFpsCallback&&this._lowFpsCallback()))}}class i{_maxMsBetweenTicks;_expectedMsBetweenTicks;_ticksMissed=1;_msBetweenTicks=0;_lastTickTime=0;_requestFrameId;_tickCallback;constructor(s,t){this._maxMsBetweenTicks=1e3/s,this._expectedMsBetweenTicks=1e3/t}start(){this._tickCallback&&(this._lastTickTime=performance.now(),this.loop())}stop(){this._requestFrameId&&(window.cancelAnimationFrame(this._requestFrameId),this._requestFrameId=void 0)}isStarted(){return!!this._requestFrameId}onTick(s){this._tickCallback=s}msBetweenTicks(){return this._msBetweenTicks}ticksMissed(){return this._ticksMissed}loop(){const s=performance.now();this._msBetweenTicks=s-this._lastTickTime,this._ticksMissed=this._msBetweenTicks/this._expectedMsBetweenTicks,this._msBetweenTicks>=this._maxMsBetweenTicks&&(this._lastTickTime=s,this._tickCallback&&this._tickCallback(this._msBetweenTicks)),this._requestFrameId=window.requestAnimationFrame(this.loop.bind(this))}}class c{_expectedMsBetweenTicks;_ticksMissed=1;_msBetweenTicks=0;_lastTickTime=0;_timeoutId;_tickCallback;constructor(s){this._expectedMsBetweenTicks=1e3/s}start(){this._tickCallback&&(this._lastTickTime=performance.now(),this.delayLoop())}stop(){this._timeoutId&&(clearTimeout(this._timeoutId),this._timeoutId=void 0)}isStarted(){return!!this._timeoutId}onTick(s){this._tickCallback=s}msBetweenTicks(){return this._msBetweenTicks}ticksMissed(){return this._ticksMissed}delayLoop(){this._timeoutId=setTimeout((()=>this.loop()),this._expectedMsBetweenTicks)}loop(){const s=performance.now();this._msBetweenTicks=s-this._lastTickTime,this._ticksMissed=this._msBetweenTicks/this._expectedMsBetweenTicks,this._lastTickTime=s,this._tickCallback&&this._tickCallback(this._msBetweenTicks),this.delayLoop()}}class a{_fps=new e;_logicTicker;_drawTicker;constructor(s){const t=s?.minFps||0,e=this.compensatedMaxFps(s?.maxFps||60),a=s?.expectedFps||60,r=s?.onLogicTick,o=s?.onDrawTick,h=s?.onLowFps;this._logicTicker=new c(a),this._drawTicker=new i(e,a),r&&this._logicTicker.onTick(r),o&&this._drawTicker.onTick((s=>{o(),this._fps.calculate(s)})),h&&this._fps.onLowFps(t,h)}start(){this._logicTicker.start(),this._drawTicker.start()}stop(){this._logicTicker.stop(),this._drawTicker.stop()}isStarted(){return this._logicTicker.isStarted()||this._drawTicker.isStarted()}fps(){return this._fps.currentFps()}msBetweenTicks(){return this._logicTicker.isStarted()?this._logicTicker.msBetweenTicks():this._drawTicker.msBetweenTicks()}ticksMissed(){return this._logicTicker.isStarted()?this._logicTicker.ticksMissed():this._drawTicker.ticksMissed()}compensatedMaxFps(s){return Math.floor(1.1*s)+10*Math.floor(s/100)}}var r=t.R;export{r as Ticker};
var s={d:(e,t)=>{for(var i in t)s.o(t,i)&&!s.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},o:(s,e)=>Object.prototype.hasOwnProperty.call(s,e)},e={};s.d(e,{R:()=>i,D:()=>a});class t{_minFps;_currentFps=60;_lastChecks=[];_calculateFpsEachMs=2e3;_msSinceLastCalculation=0;_lowFpsInRow=0;_lowFpsCallback;currentFps(){return this._currentFps}calculate(s){this.collectFps(s),this._msSinceLastCalculation+=s.deltaMs,this._msSinceLastCalculation>=this._calculateFpsEachMs&&(this._msSinceLastCalculation=0,this.calculateAverageFps(),this.checkAndNotifyLowFps())}onLowFps(s){this._lowFpsCallback=s}setMinFps(s){return this._minFps=s,this}collectFps(s){this._lastChecks.push(Math.round(1e3/s.deltaMs))}calculateAverageFps(){const s=this._lastChecks.reduce(((s,e)=>s+e),0);this._currentFps=Math.round(s/this._lastChecks.length),this._lastChecks=[]}checkAndNotifyLowFps(){this._minFps&&this._currentFps<this._minFps&&(this._lowFpsInRow++,5===this._lowFpsInRow&&(this._lowFpsInRow=0,this._lowFpsCallback&&this._lowFpsCallback()))}}class i{_fps=new t;_drawQueue=[];_logicQueue=[];_lowFpsQueue=[];_maxFps;_expectedFps;_time={delta:0,deltaMs:0};_lastTimestamp=0;_logicTicksAccumulatedMs=0;_requestFrameId;constructor(s){this.setFps({min:s?.minFps||0,max:s?.maxFps||60,expected:s?.expectedFps||60}),s?.onDrawTick&&this.addDrawTask(s.onDrawTick),s?.onLogicTick&&this.addLogicTask(s.onLogicTick),s?.onLowFps&&this.addLowFpsTask(s.onLowFps),this._fps.onLowFps((()=>{this._lowFpsQueue.forEach((s=>s.callback(this.fps())))}))}start(){this._lastTimestamp=performance.now(),this.loop(this._lastTimestamp)}stop(){this._requestFrameId&&(window.cancelAnimationFrame(this._requestFrameId),this._requestFrameId=void 0)}isStarted(){return!!this._requestFrameId}setFps(s){return s.min&&s.min>0&&this._fps.setMinFps(s.min),s.max&&s.max>0&&(this._maxFps=this.compensatedMaxFps(s.max)),s.expected&&s.expected>0&&(this._expectedFps=s.expected),this}addDrawTask(s){return{index:this._drawQueue.push({callback:s})-1,type:"draw"}}addLogicTask(s){return{index:this._logicQueue.push({callback:s})-1,type:"logic"}}addLowFpsTask(s){return{index:this._lowFpsQueue.push({callback:s})-1,type:"low-fps"}}remove(s){switch(s.type){case"draw":this._drawQueue.splice(s.index,1);break;case"logic":this._logicQueue.splice(s.index,1);break;case"low-fps":this._lowFpsQueue.splice(s.index,1)}}fps(){return this._fps.currentFps()}msBetweenTicks(){return this._time.deltaMs}ticksMissed(){return this._time.deltaMs/(1e3/this._expectedFps)}loop(s){const e=1e3/this._maxFps,t=s-this._lastTimestamp;t>=e&&(this._time={delta:t/1e3,deltaMs:t},this._lastTimestamp=s,this._fps.calculate(this._time),this.runQueue()),this._requestFrameId=window.requestAnimationFrame(this.loop.bind(this))}runQueue(){this._logicQueue.length>0&&this.runLogicQueue(),this._drawQueue.length>0&&this.runDrawQueue()}runLogicQueue(){const s=1e3/this._expectedFps;this._logicTicksAccumulatedMs+=this._time.deltaMs;const e={delta:s/1e3,deltaMs:s};for(;this._logicTicksAccumulatedMs>=s;)this._logicQueue.forEach((s=>s.callback(e))),this._logicTicksAccumulatedMs-=s}runDrawQueue(){this._drawQueue.forEach((s=>s.callback(this._time)))}compensatedMaxFps(s){return Math.floor(1.1*s)+10*Math.floor(s/100)}}class a extends i{_isStarted=!1;start(){this._isStarted=!0}stop(){this._isStarted=!1}isStarted(){return this._isStarted}fps(){return 60}msBetweenTicks(){return 1e3/60}ticksMissed(){return 1}simulateLogicTick(){this._logicQueue.forEach((s=>s.callback({delta:1/this.fps(),deltaMs:1e3/this.fps()})))}simulateDrawTick(){this._drawQueue.forEach((s=>s.callback({delta:1/this.fps(),deltaMs:1e3/this.fps()})))}simulateLowFps(){this._lowFpsQueue.forEach((s=>s.callback(this.fps())))}}var c=e.R,l=e.D;export{c as Ticker,l as TickerMock};

@@ -1,1 +0,1 @@

!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("Ticker",[],t):"object"==typeof exports?exports.Ticker=t():e.Ticker=t()}(self,(()=>(()=>{"use strict";var e={d:(t,s)=>{for(var i in s)e.o(s,i)&&!e.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:s[i]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{Ticker:()=>r});class s{_minFps;_currentFps=60;_lastChecks=[];_calculateFpsEachMs=2e3;_msSinceLastCalculation=0;_lowFpsInRow=0;_lowFpsCallback;currentFps(){return this._currentFps}calculate(e){this.collectFps(e),this._msSinceLastCalculation+=e,this._msSinceLastCalculation>=this._calculateFpsEachMs&&(this._msSinceLastCalculation=0,this.calculateAverageFps(),this.checkAndNotifyLowFps())}onLowFps(e,t){this._minFps=e,this._lowFpsCallback=t}collectFps(e){this._lastChecks.push(Math.round(1e3/e))}calculateAverageFps(){const e=this._lastChecks.reduce(((e,t)=>e+t),0);this._currentFps=Math.round(e/this._lastChecks.length),this._lastChecks=[]}checkAndNotifyLowFps(){this._minFps&&this._currentFps<this._minFps&&(this._lowFpsInRow++,5===this._lowFpsInRow&&(this._lowFpsInRow=0,this._lowFpsCallback&&this._lowFpsCallback()))}}class i{_maxMsBetweenTicks;_expectedMsBetweenTicks;_ticksMissed=1;_msBetweenTicks=0;_lastTickTime=0;_requestFrameId;_tickCallback;constructor(e,t){this._maxMsBetweenTicks=1e3/e,this._expectedMsBetweenTicks=1e3/t}start(){this._tickCallback&&(this._lastTickTime=performance.now(),this.loop())}stop(){this._requestFrameId&&(window.cancelAnimationFrame(this._requestFrameId),this._requestFrameId=void 0)}isStarted(){return!!this._requestFrameId}onTick(e){this._tickCallback=e}msBetweenTicks(){return this._msBetweenTicks}ticksMissed(){return this._ticksMissed}loop(){const e=performance.now();this._msBetweenTicks=e-this._lastTickTime,this._ticksMissed=this._msBetweenTicks/this._expectedMsBetweenTicks,this._msBetweenTicks>=this._maxMsBetweenTicks&&(this._lastTickTime=e,this._tickCallback&&this._tickCallback(this._msBetweenTicks)),this._requestFrameId=window.requestAnimationFrame(this.loop.bind(this))}}class c{_expectedMsBetweenTicks;_ticksMissed=1;_msBetweenTicks=0;_lastTickTime=0;_timeoutId;_tickCallback;constructor(e){this._expectedMsBetweenTicks=1e3/e}start(){this._tickCallback&&(this._lastTickTime=performance.now(),this.delayLoop())}stop(){this._timeoutId&&(clearTimeout(this._timeoutId),this._timeoutId=void 0)}isStarted(){return!!this._timeoutId}onTick(e){this._tickCallback=e}msBetweenTicks(){return this._msBetweenTicks}ticksMissed(){return this._ticksMissed}delayLoop(){this._timeoutId=setTimeout((()=>this.loop()),this._expectedMsBetweenTicks)}loop(){const e=performance.now();this._msBetweenTicks=e-this._lastTickTime,this._ticksMissed=this._msBetweenTicks/this._expectedMsBetweenTicks,this._lastTickTime=e,this._tickCallback&&this._tickCallback(this._msBetweenTicks),this.delayLoop()}}class r{_fps=new s;_logicTicker;_drawTicker;constructor(e){const t=e?.minFps||0,s=this.compensatedMaxFps(e?.maxFps||60),r=e?.expectedFps||60,o=e?.onLogicTick,a=e?.onDrawTick,n=e?.onLowFps;this._logicTicker=new c(r),this._drawTicker=new i(s,r),o&&this._logicTicker.onTick(o),a&&this._drawTicker.onTick((e=>{a(),this._fps.calculate(e)})),n&&this._fps.onLowFps(t,n)}start(){this._logicTicker.start(),this._drawTicker.start()}stop(){this._logicTicker.stop(),this._drawTicker.stop()}isStarted(){return this._logicTicker.isStarted()||this._drawTicker.isStarted()}fps(){return this._fps.currentFps()}msBetweenTicks(){return this._logicTicker.isStarted()?this._logicTicker.msBetweenTicks():this._drawTicker.msBetweenTicks()}ticksMissed(){return this._logicTicker.isStarted()?this._logicTicker.ticksMissed():this._drawTicker.ticksMissed()}compensatedMaxFps(e){return Math.floor(1.1*e)+10*Math.floor(e/100)}}return t})()));
!function(e,s){"object"==typeof exports&&"object"==typeof module?module.exports=s():"function"==typeof define&&define.amd?define("Ticker",[],s):"object"==typeof exports?exports.Ticker=s():e.Ticker=s()}(self,(()=>(()=>{"use strict";var e={d:(s,t)=>{for(var i in t)e.o(t,i)&&!e.o(s,i)&&Object.defineProperty(s,i,{enumerable:!0,get:t[i]})},o:(e,s)=>Object.prototype.hasOwnProperty.call(e,s),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},s={};e.r(s),e.d(s,{Ticker:()=>i,TickerMock:()=>a});class t{_minFps;_currentFps=60;_lastChecks=[];_calculateFpsEachMs=2e3;_msSinceLastCalculation=0;_lowFpsInRow=0;_lowFpsCallback;currentFps(){return this._currentFps}calculate(e){this.collectFps(e),this._msSinceLastCalculation+=e.deltaMs,this._msSinceLastCalculation>=this._calculateFpsEachMs&&(this._msSinceLastCalculation=0,this.calculateAverageFps(),this.checkAndNotifyLowFps())}onLowFps(e){this._lowFpsCallback=e}setMinFps(e){return this._minFps=e,this}collectFps(e){this._lastChecks.push(Math.round(1e3/e.deltaMs))}calculateAverageFps(){const e=this._lastChecks.reduce(((e,s)=>e+s),0);this._currentFps=Math.round(e/this._lastChecks.length),this._lastChecks=[]}checkAndNotifyLowFps(){this._minFps&&this._currentFps<this._minFps&&(this._lowFpsInRow++,5===this._lowFpsInRow&&(this._lowFpsInRow=0,this._lowFpsCallback&&this._lowFpsCallback()))}}class i{_fps=new t;_drawQueue=[];_logicQueue=[];_lowFpsQueue=[];_maxFps;_expectedFps;_time={delta:0,deltaMs:0};_lastTimestamp=0;_logicTicksAccumulatedMs=0;_requestFrameId;constructor(e){this.setFps({min:e?.minFps||0,max:e?.maxFps||60,expected:e?.expectedFps||60}),e?.onDrawTick&&this.addDrawTask(e.onDrawTick),e?.onLogicTick&&this.addLogicTask(e.onLogicTick),e?.onLowFps&&this.addLowFpsTask(e.onLowFps),this._fps.onLowFps((()=>{this._lowFpsQueue.forEach((e=>e.callback(this.fps())))}))}start(){this._lastTimestamp=performance.now(),this.loop(this._lastTimestamp)}stop(){this._requestFrameId&&(window.cancelAnimationFrame(this._requestFrameId),this._requestFrameId=void 0)}isStarted(){return!!this._requestFrameId}setFps(e){return e.min&&e.min>0&&this._fps.setMinFps(e.min),e.max&&e.max>0&&(this._maxFps=this.compensatedMaxFps(e.max)),e.expected&&e.expected>0&&(this._expectedFps=e.expected),this}addDrawTask(e){return{index:this._drawQueue.push({callback:e})-1,type:"draw"}}addLogicTask(e){return{index:this._logicQueue.push({callback:e})-1,type:"logic"}}addLowFpsTask(e){return{index:this._lowFpsQueue.push({callback:e})-1,type:"low-fps"}}remove(e){switch(e.type){case"draw":this._drawQueue.splice(e.index,1);break;case"logic":this._logicQueue.splice(e.index,1);break;case"low-fps":this._lowFpsQueue.splice(e.index,1)}}fps(){return this._fps.currentFps()}msBetweenTicks(){return this._time.deltaMs}ticksMissed(){return this._time.deltaMs/(1e3/this._expectedFps)}loop(e){const s=1e3/this._maxFps,t=e-this._lastTimestamp;t>=s&&(this._time={delta:t/1e3,deltaMs:t},this._lastTimestamp=e,this._fps.calculate(this._time),this.runQueue()),this._requestFrameId=window.requestAnimationFrame(this.loop.bind(this))}runQueue(){this._logicQueue.length>0&&this.runLogicQueue(),this._drawQueue.length>0&&this.runDrawQueue()}runLogicQueue(){const e=1e3/this._expectedFps;this._logicTicksAccumulatedMs+=this._time.deltaMs;const s={delta:e/1e3,deltaMs:e};for(;this._logicTicksAccumulatedMs>=e;)this._logicQueue.forEach((e=>e.callback(s))),this._logicTicksAccumulatedMs-=e}runDrawQueue(){this._drawQueue.forEach((e=>e.callback(this._time)))}compensatedMaxFps(e){return Math.floor(1.1*e)+10*Math.floor(e/100)}}class a extends i{_isStarted=!1;start(){this._isStarted=!0}stop(){this._isStarted=!1}isStarted(){return this._isStarted}fps(){return 60}msBetweenTicks(){return 1e3/60}ticksMissed(){return 1}simulateLogicTick(){this._logicQueue.forEach((e=>e.callback({delta:1/this.fps(),deltaMs:1e3/this.fps()})))}simulateDrawTick(){this._drawQueue.forEach((e=>e.callback({delta:1/this.fps(),deltaMs:1e3/this.fps()})))}simulateLowFps(){this._lowFpsQueue.forEach((e=>e.callback(this.fps())))}}return s})()));

@@ -1,8 +0,26 @@

export interface TickerOptionsInterface {
export interface TickerOptions {
/**
* @deprecated Passing `maxFps` in ticker options is deprecated. Use `ticker.setFps({ max: 60 })` instead.
*/
maxFps?: number;
/**
* @deprecated Passing `expectedFps` in ticker options is deprecated. Use `ticker.setFps({ min: 10 })` instead.
*/
minFps?: number;
/**
* @deprecated Passing `expectedFps` in ticker options is deprecated. Use `ticker.setFps({ expected: 60 })` instead.
*/
expectedFps?: number;
/**
* @deprecated Passing `onLogicTick` in ticker options is deprecated. Use `ticker.addLogicTask(callback)` instead.
*/
onLogicTick?: () => void;
/**
* @deprecated Passing `onDrawTick` in ticker options is deprecated. Use `ticker.addDrawTask(callback)` instead.
*/
onDrawTick?: () => void;
/**
* @deprecated Passing `onLowFps` in ticker options is deprecated. Use `ticker.addLowFpsTask(callback)` instead.
*/
onLowFps?: () => void;
}
{
"name": "@armniko/ticker",
"version": "1.1.0",
"version": "2.0.0",
"description": "Javascript/typescript library for running app loop with separate logical/drawing ticks and FPS limitation.",

@@ -5,0 +5,0 @@ "author": "Armīns Nikolajevs <armins.nikolajevs@gmail.com>",

+69
-40

@@ -21,58 +21,79 @@ <h1 align="center">Ticker</h1>

```typescript
import {Ticker} from '@armniko/ticker';
import {Ticker, Time} from '@armniko/ticker';
const ticker: Ticker = new Ticker({
onLogicTick: (): void => {
// update logic
},
onDrawTick: (): void => {
// draw
},
const element: { position: { x: number, y: number } } = {position: {x: 0, y: 0}};
const animation: { durationMs: number, distancePx: number } = {
durationMs: 2000,
distancePx: 500,
}
const ticker: Ticker = new Ticker();
ticker.addLogicTask((time: Time): void => {
const pxPerMs: number = animation.distancePx / animation.durationMs;
element.position.x += pxPerMs * time.deltaMs;
});
ticker.start();
ticker.addDrawTask((): void => {
// draw
});
```
Ticker constructor accepts options object with attributes:
Ticker instance methods:
- minFps (default: 0) - defines value at which onLowFps callback will be called.
- maxFps (default: 60) - defines drawing FPS limit.
- expectedFps (default: 60) - defines expected logical and drawing FPS at which app should work in normal conditions.
- onLogicTick (default: undefined) - callback for update app logic.
- onDrawTick (default: undefined) - callback for update app screen.
- onLowFps (default: undefined) - callback that will be called when reached minFps.
- start() - starts ticker.
- stop() - stops ticker.
- isStarted() - checks if ticker is started.
- setFps(options: { min?: number; max?: number; expected?: number }) - set min, max or expected FPS
- min (default: 0) - defines value at which lowFps task callbacks will be called.
- max (default: 60) - defines drawing FPS limit.
- expected (default: 60) - defines expected logical and drawing FPS at which app should work in normal conditions.
- addLogicTask(callback) - register callback for update app logic. Returns TickerTaskId.
- addDrawTask(callback) - register callback for update app screen. Returns TickerTaskId.
- addLowFpsTask(callback) - register callback that will be called when reached min FPS. Returns TickerTaskId.
- remove(taskId: TickerTaskId) - removes provided task.
- fps() - current FPS at witch app operate.
To compensate missed ticks, use msBetweenTicks() and ticksMissed() Ticker methods when calculate logic.
## Migration
### v1 -> v2
Before (v1):
```typescript
// frames based animation
let x: number = 0;
const pxPerTick: number = 3;
const ticker: Ticker = new Ticker({
onLogicTick: (): void => {
x += pxPerTick * ticker.ticksMissed();
}
});
```
import {Ticker} from '@armniko/ticker';
```typescript
// time based animation
let x: number = 0;
const animationDurationMs: number = 2000;
const distancePx: number = 500;
const pxPerMs: number = distancePx / animationDurationMs;
const element: { position: { x: number, y: number } } = {position: {x: 0, y: 0}};
const animation: { durationMs: number, distancePx: number } = {
durationMs: 2000,
distancePx: 500,
}
const ticker: Ticker = new Ticker({
onLogicTick: (): void => {
x += pxPerMs * ticker.msBetweenTicks();
}
const pxPerMs: number = distancePx / animationDurationMs;
element.position.x += pxPerMs * ticker.msBetweenTicks();
},
onDrawTick: (): void => {
// draw element
},
});
ticker.start();
```
Under the hood Ticker collects draw metrics and calculate current FPS. This value can be retrieved from Ticker:
After (v2):
```typescript
const ticker = new Ticker({
onDrawTick: (): void => {
console.log(ticker.fps());
}
import {Ticker, Time} from '@armniko/ticker';
const element: { position: { x: number, y: number } } = {position: {x: 0, y: 0}};
const animation: { durationMs: number, distancePx: number } = {
durationMs: 2000,
distancePx: 500,
}
const ticker: Ticker = new Ticker();
ticker.addLogicTask((time: Time): void => {
const pxPerMs: number = distancePx / animationDurationMs;
element.position.x += pxPerMs * time.deltaMs;
});
ticker.addDrawTask((): void => {
// draw element
});
ticker.start();
```

@@ -84,5 +105,13 @@

<tr>
<td>v2.0.0</td>
<td>
Multiple tick callbacks support<br>
Added TickerMock for testing<br>
Deprecated: constructor options, msBetweenTicks(), ticksMissed(). (See migration v1 -> v2)
</td>
</tr>
<tr>
<td>v1.1.0</td>
<td>
Precompile UMD and ESM<br>
Precompile UMD and ESM
</td>

@@ -89,0 +118,0 @@ </tr>

export declare class Fps {
private _minFps?;
private _currentFps;
private _lastChecks;
private _calculateFpsEachMs;
private _msSinceLastCalculation;
private _lowFpsInRow;
private _lowFpsCallback?;
currentFps(): number;
calculate(msSinceLastTick: number): void;
onLowFps(minFps: number, callback: () => void): void;
private collectFps;
private calculateAverageFps;
private checkAndNotifyLowFps;
}
import { TickerOptionsInterface } from '../interfaces/ticker-options.interface';
export declare class Ticker {
private readonly _fps;
private _logicTicker;
private _drawTicker;
constructor(options?: TickerOptionsInterface);
start(): void;
stop(): void;
isStarted(): boolean;
fps(): number;
msBetweenTicks(): number;
ticksMissed(): number;
private compensatedMaxFps;
}
export declare class DrawTicker {
private readonly _maxMsBetweenTicks;
private readonly _expectedMsBetweenTicks;
private _ticksMissed;
private _msBetweenTicks;
private _lastTickTime;
private _requestFrameId?;
private _tickCallback?;
constructor(maxFps: number, expectedFps: number);
start(): void;
stop(): void;
isStarted(): boolean;
onTick(callback: (msSinceLastTick: number) => void): void;
msBetweenTicks(): number;
ticksMissed(): number;
private loop;
}
export declare class LogicTicker {
private readonly _expectedMsBetweenTicks;
private _ticksMissed;
private _msBetweenTicks;
private _lastTickTime;
private _timeoutId?;
private _tickCallback?;
constructor(expectedFps: number);
start(): void;
stop(): void;
isStarted(): boolean;
onTick(callback: (msSinceLastTick: number) => void): void;
msBetweenTicks(): number;
ticksMissed(): number;
private delayLoop;
private loop;
}