agentscript
Version:
AgentScript Model in Model/View architecture
118 lines (105 loc) • 3.33 kB
JavaScript
import Stats from '../vendor/stats.js'
/**
* Class Animator controls running of a function.
*/
class Animator {
/**
* Sets parameters, then calls start().
* To have the model not start immediately do:
* - const anim = new Animator(\<args>).stop()
*
* @param {Function} fcn The function the animator runs and controls
* @param {number} steps How many steps to run. Default is -1, forever
* @param {number} fps Max frames/second to run. Default is 30
*/
constructor(fcn, steps = -1, fps = 30) {
Object.assign(this, { fcn, steps, fps, ticks: 0 })
this.stats = null
this.timeoutID = null
this.idle = null
this.idleFps = null
this.idleID = null
this.start()
}
/**
* Starts the model running
*
* @returns The animator, allows chaining
*/
start() {
// if (this.timeoutID) return // avoid multiple starts
this.clearIDs()
this.timeoutID = setInterval(() => this.step(), 1000 / this.fps)
// if (this.idleID) this.idleID = clearInterval(this.idleID)
return this // chaining off ctor
}
/**
* Stops the model running
*
* @returns The animator, allows chaining
*/
stop() {
// if (this.timeoutID) this.timeoutID = clearInterval(this.timeoutID)
// if (this.idleID) this.idleID = clearInterval(this.idleID)
this.clearIDs()
if (this.idle)
this.idleID = setInterval(() => this.idle(), 1000 / this.idleFps)
return this // chaining off ctor
}
step() {
// if (this.steps === 0) return this.stop()
if (this.ticks === this.steps) return this.stop()
this.ticks++
// this.steps--
this.fcn()
if (this.stats) this.stats.update()
return this // chaining off ctor
}
clearIDs() {
if (this.timeoutID) this.timeoutID = clearInterval(this.timeoutID)
if (this.idleID) this.idleID = clearInterval(this.idleID)
}
isRunning() {
return this.timeoutID != null
}
startStats(left = '0px') {
if (this.stats) return console.log('startStats: already running')
this.stats = new Stats()
document.body.appendChild(this.stats.dom)
this.stats.dom.style.left = left
return this // chaining off ctor
}
setFps(fps) {
this.reset(this.steps, fps)
}
setSteps(steps) {
this.reset(steps, this.fps)
}
// set the new steps & fps, restStart if currently running
reset(steps = this.steps, fps = this.fps) {
const wasRunning = this.isRunning()
if (wasRunning) this.stop()
this.steps = steps
this.ticks = 0
this.fps = fps
if (wasRunning) this.start()
}
// stop if running, start otherwise
// if starting and steps === 0, reset with steps = -1, forever.
toggle() {
// if (this.timeoutID) this.stop()
if (this.isRunning()) this.stop()
// else if (this.steps === 0) this.reset()
else this.start()
}
// call the fcn once. stops if currently running
once() {
this.stop()
this.step()
}
setIdle(fcn, fps = 4) {
this.idle = fcn
this.idleFps = fps
}
}
export default Animator