Controlling spritesheet animation speed programmatically (DEF-1590)

Once an animation is defined from a group of images in the Outline of an Atlas, I can set its FPS to a value I like, however I couldn’t find a documented way to programmatically control sprite sheet animation speed.

I’m thinking about two work-arounds: defining animations with suffixes like run_10fps, run_11fps, run_12fps, etc for different FPS and switching between these animations programmatically - which will most likely cause animation cycle synchronisation issues; alternatively - I can try and create my own sprite sheet animation system on top of Defold and switch the sprites programmatically (one-frame animation per each frame of the cycle).

Am I missing anything?

6 Likes

It’s correct that there is no way to programmatically control the sprite sheet animation speed. All I can think of is doing exactly what you are doing I’m afraid.

I’ve created a ticket for it (DEF-1590). Let’s see if one of the engine guys can provide some feedback.

3 Likes

Thank you @britzl. At least there’s a workaround I can use right now!

1 Like

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!

7 Likes

Nice! Thanks for sharing!

1 Like

This workaround is good, but it’s planned to be added in the engine?

So strange to use workaround for this.

Thanks.

2 Likes

Yes, it’s in our backlog but it hasn’t been assigned to a future release though.

3 Likes

I am using this workaround, too.
Would be nice to replace it by engine method.

3 Likes

Hello @britzl ,

I don’t know its a dump question but, I wonder if your backlog covers spine animation speed. I couldn’t find a away to control it.

Best Regards,

Yes, this is covered by a ticket in our backlog. I don’t have access to it right now though so I can’t see it’s priority.

1 Like

Is there any news?

1 Like

Yes, the changes related to speed, playback offsets, etc. is being designed right now. :slight_smile: Sorry for the poor follow-up in this thread.

8 Likes

Is there any updates on this issue, or is the workaround the way to go at the moment?

1 Like

Yes, I’m afraid so.