Source: Animation.js

import * as BAGEL from "./index.js";

/**
 * An Animation is similar to a {@link Texture} but designed for drawing images from a spritesheet
 *   (a grid of images), with methods to automatically update
 */
class Animation
{

	/**
	 * Load image file and create list of regions depending on number of rows and columns in spritesheet.
	 * @param {string} filename the name (including path) of the image file  
	 * @param {number} rows - the number of rows in the spritesheet
	 * @param {number} cols - the number of columns in the spritesheet
	 * @param {number} frameDuration - time (seconds) to display each frame (region in spritesheet)
	 * @param {boolean} loop - whether to restart animation once all frames have been displayed
	 * @constructor
	 */
	constructor(fileName, rows=1, cols=1, frameDuration=0.25, loop=false)
	{
		this.texture  = new BAGEL.Texture();
		this.regionList = [];
		this.elapsedTime = 0;
		this.paused = false;

		this.frameDuration = 0.25;
		this.totalDuration = null;
		this.loop = false;

		// only try to load a file if a fileName is given
		// (this will not be the case when cloning an Animation)
		if ( fileName )
		{
			let self = this;

			// this code automatically runs after image data loaded
			this.texture.image.onload = function()
			{

				// create list of rectangles
				let frameWidth  = self.texture.image.width  / cols;
				let frameHeight = self.texture.image.height / rows;			
				for (let y = 0; y < rows; y++)
		        {
		            for (let x = 0; x < cols; x++)
		            {
						let region = new BAGEL.Rectangle(x*frameWidth, y*frameHeight, frameWidth, frameHeight)
		                self.regionList.push( region );
		            }
		        }
		        self.texture.region = self.regionList[0];

		        self.frameDuration = frameDuration;
				self.totalDuration  = frameDuration * self.regionList.length;
		        self.loop = loop;
			}

			this.texture.image.src = fileName;
		}
	}
	

	/**
	 * Updates elapsedTime and updates the rectangular region used by texture
	 *  depending on how much time has elapsed.
	 */
    update(deltaTime)
    {
        if (this.paused)
			return;
			
        this.elapsedTime += deltaTime;
    
    	// check if loop is reset
		if (this.loop && this.elapsedTime > this.totalDuration)
            this.elapsedTime -= this.totalDuration;
		
        let regionIndex = Math.floor( this.elapsedTime / this.frameDuration );
        if ( regionIndex >= this.regionList.length )
            regionIndex = this.regionList.length - 1;
		this.texture.region = this.regionList[regionIndex];
    }

	/**
	 *  Determines if this animation is finished displaying all frames (and is not set to loop).
	 *  @return {boolean} if this animation has finished
	 */
    isFinished()
    {
        return (this.elapsedTime >= this.regionList.length * this.frameDuration) && !this.loop;
    }

	/**
	 *  Make a copy of this object.
	 *  <br>An animation object can not be shared between multiple sprites because each
	 *   may have started at different times, thus have different elapsedTime values.
	 *  @return {Animation} a copy of this Animation object
	 */
    clone()
    {
        let anim            = new BAGEL.Animation();
        anim.texture.image  = this.texture.image;
        anim.texture.region = this.regionList[0];
		anim.regionList     = this.regionList;
        anim.frameDuration  = this.frameDuration;
		anim.totalDuration  = this.totalDuration;
        anim.loop           = this.loop;
        return anim;
    }

}


export { Animation };