Source: plain-animator.js

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PlainAnimator = void 0;
const rxjs_1 = require("rxjs");
const three_1 = require("three");
/**
 * Basic Animator Class
 *
 * allows to animate texture in loop
 *
 * @example
 * const spriteTexture = new THREE.TextureLoader().load('sprite-texture.png')
 * const animator = new PlainAnimator(spriteTexture, 4, 4, 10, 15);
 * const texture = animator.init();
 * animator.animate();
 *
 * @see {@link https://github.com/MaciejWWojcik/three-plain-animator/tree/master/src/examples/simple-2d-animation/src/index.ts)}
 */
class PlainAnimator {
    /**
     * Create a PlainAnimator
     * @param {Texture} texture - THREE Texture object with sprite image loaded
     * @param {number} tilesAmountHorizontally - number of columns in your sprite image
     * @param {number} tilesAmountVertically - number of rows in your sprite image
     * @param {number} tilesTotalAmount - number of frames in your sprite image
     * @param {number} framesPerSecond - number of frames per second, for example 15
     */
    constructor(texture, tilesAmountHorizontally, tilesAmountVertically, tilesTotalAmount, framesPerSecond) {
        this.texture = texture;
        this.tilesAmountHorizontally = tilesAmountHorizontally;
        this.tilesAmountVertically = tilesAmountVertically;
        this.tilesTotalAmount = tilesTotalAmount;
        this.currentFrameDisplayTime = 0;
        this.currentFrame = 0;
        this.clock = new three_1.Clock();
        this.end$ = new rxjs_1.Subject();
        this.tilesTotalAmount -= 1; // indexing from 0
        this.frameDisplayDuration = 1000 / framesPerSecond;
        this.texture.wrapS = three_1.RepeatWrapping;
        this.texture.wrapT = three_1.RepeatWrapping;
        this.texture.repeat.set(1 / tilesAmountHorizontally, 1 / tilesAmountVertically);
    }
    /**
     * Initializes Animator,
     * @param {number} startFrame - optional parameter for setting the start position of animation (frame number)
     * @return {Texture} a Texture object that will display animation
     */
    init(startFrame = 0) {
        this.currentFrame = startFrame;
        this.currentFrameDisplayTime = 0;
        this.clock = new three_1.Clock();
        this.updateFrame();
        return this.texture;
    }
    /**
     * Updates current frame in Texture, should be invoked in loop to allow updating the texture
     *
     * @example
     * function animate() {
     *    animator.animate();
     *    requestAnimationFrame(animate);
     *  }
     *
     */
    animate() {
        this.currentFrameDisplayTime += this.clock.getDelta() * 1000;
        while (this.currentFrameDisplayTime > this.frameDisplayDuration) {
            this.currentFrameDisplayTime -= this.frameDisplayDuration;
            if (this.currentFrame === this.tilesTotalAmount) {
                this.end$.next();
            }
            this.currentFrame = this.currentFrame < this.tilesTotalAmount ? this.currentFrame + 1 : 0;
            this.updateFrame();
        }
    }
    /**
     * Getter for Observable that emits event on end of the animation
     * note that when used in infinity loop, the event will be emitted every time animation completes
     * @return {Observable} a void Observable
     */
    get end() {
        return this.end$.asObservable();
    }
    updateFrame() {
        const tileHeight = 1 / this.tilesAmountVertically;
        const currentColumn = this.currentFrame % this.tilesAmountHorizontally;
        const currentRow = Math.floor(this.currentFrame / this.tilesAmountHorizontally);
        this.texture.offset.x = currentColumn / this.tilesAmountHorizontally;
        this.texture.offset.y = 1 - currentRow / this.tilesAmountVertically - tileHeight;
    }
}
exports.PlainAnimator = PlainAnimator;