@inglorious/engine
Version:
A JavaScript game engine written with global state, immutability, and pure functions in mind. Have fun(ctional programming) with it!
50 lines (43 loc) • 1.93 kB
JavaScript
const DEFAULT_STATE = "default"
const DEFAULT_VALUE = 0
const COUNTER_RESET = 0
export const Ticker = {
/**
* Ticks a counter and calls a function when a target interval is reached.
*
* @param {object} options The options for the tick.
* @param {object} options.target An object to hold the ticker's internal state.
* @param {number} options.target.speed The interval in milliseconds for the ticker to "tick".
* @param {number} options.dt The time elapsed since the last tick.
* @param {function} options.onTick The function to call when the ticker "ticks".
* @param {string} [options.state="default"] An optional state to track changes and reset the ticker.
* @param {number} [options.defaultValue=0] The default value for the target's counter.
*/
tick({ target, state = DEFAULT_STATE, dt, onTick, ...options }) {
const missing = [target == null && "'target'", dt == null && "'dt'"]
.filter(Boolean)
.join(", ")
if (missing.length) {
throw new Error(`Ticker.tick is missing mandatory parameters: ${missing}`)
}
const { speed, defaultValue = DEFAULT_VALUE } = target
// The `state` property on a sprite is used to declare the desired animation.
// The Ticker needs its own internal property to track the *current* animation
// to detect when it changes. We'll use `target.animation`.
if (state !== target.animation) {
target.animation = state
target.counter = COUNTER_RESET
target.value = defaultValue
}
// Always ensure the public `state` property reflects the intended animation for `onTick`.
target.state = state
// Ensure properties are initialized on the first run for a given target.
target.counter ??= COUNTER_RESET
target.value ??= defaultValue
target.counter += dt
if (target.counter >= speed) {
target.counter = COUNTER_RESET
onTick?.(target, dt, options)
}
},
}