Source: utils/lerp.js

/* 
 * File: lerp.js
 *       Encapsulates the LERP function
 */
"use strict";


// value: target for interpolation
// cycles: integer, how many cycle it should take for a value to change to final
// rate: the rate at which the value should change at each cycle
class Lerp {
    /**
     * @classdesc Encapsulates the linear interpolation functionality 
     * <p>Found in Chapter 7, page 347 of the textbook</p>
     * Example:
     * {@link https://mylesacd.github.io/build-your-own-2d-game-engine-2e-doc/BookSourceCode/chapter7/7.2.camera_interpolations/index.html 7.2 Camera Interpolations}
     * 
     * @constructor
     * @param {float} value  - starting value of interpolation
     * @param {integer} cycles - number of cycles it should take to reach the target value
     * @param {float} rate - rate at which the value should change at each cycle
     * @returns {Lerp} a new Lerp instance
     */
    constructor(value, cycles, rate) {
        this.mCurrentValue = value;    // begin value of interpolation
        this.mFinalValue = value;      // final value of interpolation
        this.mCycles = cycles;
        this.mRate = rate;

        // if there is a new value to interpolate to, number of cycles left for interpolation
        this.mCyclesLeft = 0;
    }
    /**
     * Returns the current value of this Lerp
     * @method
     * @returns {float} mCurrentValue - the current value of this Lerp
     */
    get() { return this.mCurrentValue; }

    /**
     * Sets the final value for this Lerp and starts interpolation
     * @method
     * @param {float} v - the target value to be set
     */
    setFinal(v) {
        this.mFinalValue = v;
        this.mCyclesLeft = this.mCycles;     // will trigger interpolation
    }

    /**
     * Method called by Gameloop, interpolates value if there are remaining cycles
     * @method
     * @return {void}
     */
    update() {
        if (this.mCyclesLeft <= 0) {
            return;
        }

        this.mCyclesLeft--;
        if (this.mCyclesLeft === 0) {
            this.mCurrentValue = this.mFinalValue;
        } else {
            this._interpolateValue();
        }
    }

    // stiffness of 1 switches off interpolation
    /**
     * Sets the rate and number of cyles of this Lerp
     * @method
     * @param {float} stiffness - the new rate for this Lerp
     * @param {integer} duration - the new number of cycles for this Lerp
     */
    config(stiffness, duration) {
        this.mRate = stiffness;
        this.mCycles = duration;
    }

    // subclass should override this function for non-scalar values
    /**
     * Calculates the next value using the current value, rate, and diffence between current and target.
     * Internally called by update
     * @method
     */
    _interpolateValue() {
        this.mCurrentValue = this.mCurrentValue + this.mRate * (this.mFinalValue - this.mCurrentValue);
    }
}

export default Lerp;