local Object = require "lib/classic" ---@class Frame ---@field sprite number The index of the sprite in the atlas. ---@field duration? number The duration (in seconds) of this frame. ---@field atlas? Atlas The sprite atlas this frame is drawn from. ---@class Animation ---A timed sequence of sprites. local Animation = Object:extend() ---Creates a new animation. ---@param frames Frame[] A list of frames. ---@param duration? number The default duration to use for this animation. Defaults to 15 FPS. ---@param atlas? Atlas The default atlas to use for this animation. function Animation:new(frames, duration, atlas) local default_duration = duration or (1.0 / 15.0) ---The list of frames. self.frames = {} local total_duration = 0 for idx, frame in ipairs(frames) do total_duration = total_duration + (frame.duration or default_duration) self.frames[idx] = { sprite = frame.sprite, duration = frame.duration or duration, atlas = frame.atlas or atlas or error("Missing default atlas"), } end ---The total duration of this animation. self.duration = total_duration end ---Creates a new animation from the sprites between start and end indices, plus an atlas. ---@param atlas Atlas The atlas that the sprites are from. ---@param start_idx number The first sprite index in the animation. ---@param end_idx number The last sprite index in the animation. ---@param duration? number The duration of each frame. Defaults to 15 FPS. ---@return Animation function Animation:new_spanned(atlas, start_idx, end_idx, duration) local duration = duration or (1.0 / 15.0) local frames = {} for sprite = start_idx, end_idx do frames[#frames + 1] = { sprite = sprite, atlas = atlas, duration = duration } end return Animation(frames) end ---Draws a frame of this animation. ---@param index number The index of the frame. ---@param x number The X position to draw at. ---@param y number The Y position to draw at. function Animation:draw(index, x, y) local frame = self.frames[index] frame.atlas:draw(frame.sprite, x, y) end return Animation