I’ve needed the same functionality and based on second workaround I’ve prepared simple animation function which does the job using Atlas-based manual animation
First you need to prepare your atlas a bit differently - don’t aggregate your animation frames in animations. Just place the frames in your atlas.
Then use this function:
-- animation [table] - animation description table with following members:
-- * object [string] - url of the sprite which will be animated
-- * time [float] - current time of animation. Elapsed value since start of animaton in seconds. pass 0.0 to start from begining of animation.
-- * duration [float] - animation duration in second. Must be greater than 0.0
-- * time_scale [float] - scalar of animation speed. 1.0 - default speed, 2.0 - double speed, 0.5 - half speed, etc.
-- * frames [table] - a table with animation frames, which are strings of names of your animation frames, e.g. {"frame1", "frame2", "frame3"}
-- * finish_callback - callback function which will be fired when animation finished. May be nil. Will be fired only in case of non-looped animations.
-- dt [float] - time since last frame in seconds.
function update_animation(animation, dt)
if animation.loop == false and animation.time == animation.duration then
return
end
animation.time = animation.time + dt * animation.time_scale
if animation.time > animation.duration then
if animation.loop then
while animation.time > animation.duration do
animation.time = animation.time - animation.duration
end
else
animation.time = animation.duration
end
end
local frames_count = table.getn(animation.frames)
local current_frame = math.min(math.floor((animation.time / animation.duration) * frames_count) + 1, frames_count)
msg.post(animation.object, "play_animation", {id = hash(animation.frames[current_frame])})
if animation.time == animation.duration and not animation.loop and animation.finish_callback ~= nil then
animation.finish_callback()
end
end
You can put the function into a module or use it directly.
The usage is quite simple:
function init(self)
self.idle_animation =
{
object = "#sprite",
time = 0,
duration = 0.4,
time_scale = 1.0,
loop = true,
frames =
{
"frame_0", "frame_1", "frame_2", "frame_3", "frame_4"
},
finish_callback = nil
}
end
function update(self, dt)
update_animation(self.idle_animation, dt)
end
I hope that helps!