mirror of
https://github.com/NohamR/Pocket-Bird.git
synced 2026-05-25 12:17:22 +00:00
92 lines
2.4 KiB
JavaScript
92 lines
2.4 KiB
JavaScript
import Frame from "./frame.js";
|
|
import { BirdType } from "./sprites";
|
|
|
|
class Anim {
|
|
/**
|
|
* @param {Frame[]} frames
|
|
* @param {number[]} durations
|
|
* @param {boolean} loop
|
|
*/
|
|
constructor(frames, durations, loop = true) {
|
|
this.frames = frames;
|
|
this.durations = durations;
|
|
this.loop = loop;
|
|
this.lastFrameIndex = -1;
|
|
this.lastDirection = null;
|
|
this.lastTimeStart = null;
|
|
}
|
|
|
|
getAnimationDuration() {
|
|
return this.durations.reduce((a, b) => a + b, 0);
|
|
}
|
|
|
|
/**
|
|
* Get the current frame index based on elapsed time
|
|
* @param {number} time The elapsed time since animation start
|
|
* @returns {number} The index of the current frame
|
|
*/
|
|
getCurrentFrameIndex(time) {
|
|
let totalDuration = 0;
|
|
for (let i = 0; i < this.durations.length; i++) {
|
|
totalDuration += this.durations[i];
|
|
if (time < totalDuration) {
|
|
return i;
|
|
}
|
|
}
|
|
return this.frames.length - 1;
|
|
}
|
|
|
|
/**
|
|
* Clear the cached frame state
|
|
*/
|
|
#clearCache() {
|
|
this.lastFrameIndex = -1;
|
|
this.lastDirection = null;
|
|
}
|
|
|
|
/**
|
|
* Check if the frame needs to be redrawn
|
|
* @param {number} frameIndex The current frame index
|
|
* @param {number} direction The current direction
|
|
* @returns {boolean} Whether the frame needs to be redrawn
|
|
*/
|
|
#shouldRedraw(frameIndex, direction) {
|
|
return frameIndex !== this.lastFrameIndex || direction !== this.lastDirection;
|
|
}
|
|
|
|
/**
|
|
* @param {CanvasRenderingContext2D} ctx
|
|
* @param {number} direction
|
|
* @param {number} timeStart The start time of the animation in milliseconds
|
|
* @param {number} canvasPixelSize The size of a canvas pixel in pixels
|
|
* @param {BirdType} [species] The species to use for the animation
|
|
* @returns {boolean} Whether the animation is complete
|
|
*/
|
|
draw(ctx, direction, timeStart, canvasPixelSize, species) {
|
|
// Reset cache if animation was restarted
|
|
if (this.lastTimeStart !== timeStart) {
|
|
this.#clearCache();
|
|
this.lastTimeStart = timeStart;
|
|
}
|
|
|
|
let time = Date.now() - timeStart;
|
|
const duration = this.getAnimationDuration();
|
|
|
|
if (this.loop) {
|
|
time %= duration;
|
|
}
|
|
|
|
const currentFrameIndex = this.getCurrentFrameIndex(time);
|
|
|
|
if (this.#shouldRedraw(currentFrameIndex, direction)) {
|
|
this.frames[currentFrameIndex].draw(ctx, direction, canvasPixelSize, species);
|
|
this.lastFrameIndex = currentFrameIndex;
|
|
this.lastDirection = direction;
|
|
}
|
|
|
|
// Return whether animation is complete (for non-looping animations)
|
|
return !this.loop && time >= duration;
|
|
}
|
|
}
|
|
|
|
export default Anim; |