SpriteLoop + Defold Extension Development Log

nice thanks for the answer!
Ok I was using it wrong, fair enough :smiley:
So yeah the workflow totally makes sense, I will try again with a new character.
For the guide frame, it is still useful, but as I said controlling showing effective pixel size could be really useful to set up the desired output without rescaling.

I am waiting your thoughts on the atlas thing :wink:

And I want to try to mix your tool with panthera to build a cutscene/complex animation of animated game objects, will keep you updated!

1 Like

Defold Extension

Yes, at the moment it does not use Defold atlases.

Instead, it loads the images once, “bakes” all frames for the selected animation, and then passes those frames directly to Defold for rendering. It does not build Defold atlases at runtime.

From my experience, Defold handles multiple atlases pretty well. On the extension side, there is probably room to optimize how frames are baked and reused, but I need to build a few real games with it before I can properly evaluate the performance characteristics.

So far, all my tests have been done with a single animation. The extension caches the generated frames, and in that scenario it performs well with up to 5,000 instances. The results will probably be different when dealing with many unique animations.

At the moment, I don’t want to integrate directly with Defold atlases because that would tightly couple the .spla format to Defold-specific systems, and I’m not familiar enough with all of the engine internals yet.

When images are added to an atlas, their positions change, they may be rotated, and other packing optimizations can be applied. Off the top of my head, that sounds considerably more complex to manage, and it’s not something I want to tackle right now.

Personally, I don’t enjoy the workflow of having to select an atlas every time I create a sprite. I know it’s generally better for performance, but it can become a bit tedious over time.

That said, I completely agree that atlas support could improve performance in the future and would allow image reuse, which is not possible at the moment. On the other hand, if you have many characters with multiple skins, you’re probably not going to fit all of those images into a single atlas anyway.

As for the .spriteloop format, yes, it duplicates your source images. The goal, however, was to make projects easy to share.

An alternative would be to keep the metadata in a separate file and have users zip the entire working directory, but that felt cumbersome to me. Instead, I went with an all-in-one format. Internally, a .spriteloop file is basically just a ZIP archive in disguise.

P.S. The coloris used for the animated opacity of the parts. There maybe some leftovers in the material.

To improve the “Parent Link” workflow for arms, legs, and other limb chains, I’m currently working on a new Smart Limb feature for the editor.

In the example below, most of the keyframes are placed on the torso, with only a few keyframes on the violet target controls used to define the arm and leg poses.

Limbs can optionally be stretched, which is especially useful for organic characters and more cartoony animation styles. A talented artist or animator can combine this with perspective-aware drawing to create surprisingly convincing illusions of depth and movement, making the animation feel much more natural.

The good news is that I’ve already added skew and scale support to the Defold extension, so Smart Limb animations should work out of the box in Defold once the update lands.




13 Likes

This is totally awsome!

If you add anchor points/anchor vectors, events emitting, and a defold API to parent game objects to anchor points (or register a callback to attach to the point when it changes? Could be the same for events, just register a callback by event name)
your tool can replace Spine for like 90% of use case

5 Likes

OK I tried again the parent-link feature and it is nice!

cloudstrifeanim

(graphics parts thanks to IA!)

But this was not so easy, I am eagerly waiting for the Smart limb feature!

Some new takeaways:

  • could be really useful to be allow to duplicate a part, without reimporting the same png. For example here for 2 sword handling, or thing we need left and right but flipped
  • allow CTRL+CLICK or SHIF-CLICK to select multiple parts. We can do it in the list on the left, but we want just click in the image…
  • when selecting multiple parts, we can scale or move all of them with mouse, but we cant set the scale or position with panel => allow setting “current selection transform” in right panel when selecting multiple parts.
  • I think we definitely need to SEE the other timelines of other parts (the ones that have keyframes), so we can see were are the keyframes. For example here I set my torse keyframes, the animate the rest. But I wasn’t always sure to be on the same torse keyframe.
2 Likes

Nice one! The first two are already in. I also made some other QOL improvements and bug fixes. I’m going to ship it in a few minutes unless I find another bug to fix. :sweat_smile:

I agree! Multiple timelines can improve the workflow. I myself ended up clicking multiple times on the body so I can find the exact keyframe for the arms etc. I will think how to add it as an option.

Adding this to the todo list.

P.S. v0.8.0 is live now.

3 Likes

Wouaw this is evolving lightspeed fast!

I made a new one using the Smart limbs controls
cloudstrifeanimattack
and this was waaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaayyyyyyyyyyyyyyyyyyyy easier than on v0.7!
Congrats this is so cool (yeah I am total hyped by your tool :grin: )

My feedback on the new features:

  • I think the smart controls

    should also appear when we select a control, here

    so we can configure it while testing/moving it. Right now we need to click back (and remember) on the part that created this limb…but then can’t move the control…
  • need some explanation in the tool on how to use, and especially on the different parameters of influence, sofness, max stretch and stretch falloff, I played with them but didnt understand everything :sweat_smile:
  • all QOL evolutions are great

Finally, I was thinking again about the defold API for runtime anchors/events, and I think you really dont need more concepts in the Editor. I think you could just add an API in Defold extension that permit to register a callback attached to some parts, the callback beeing called everytime some value of its transforms has changed.
The usage would be something like this in a gameobject script for our hero, so that it has a weapon that is a true game object that will replace the part in the animation:

local spriteloop = require "spriteloop.spriteloop"

--- callback for spriteloop: self is the context passed while registering,
--- part is the part name
--- animation is the currently playing animation
--- data contains all transform data and other useful data (frame number?)
local function weapon_callback(self,  part, animation, data)
 -- real weapon object follow the hand while animating
  go.set_position(data.position, self.weapon_url)   -- here position is a vector3 with z=0 already
  go.set_rotation(data.rotation, self.weapon_url ) -- here rotation is a quaternion already
 -- here we handle events in the animation. 
 if data.event then 
 -- for attack, collision of the weapon should be activated only between some frames.
  if data.event == 'hit_frame_start' then 
     -- activate weapon collision object
       msg.post(self.weapon_collision, "enable") 
   elseif data.event == 'hit_frame_end' then
     -- deactivate weapon collision object 
          msg.post(self.weapon_collision, "disable") 
   elseif data.event == 'weapon_sound' then 
         play_sound('weapon_sound') 
   end
 end
end


--- for footsteps sound and dust fx:
local function footstep_callback(self,  part, animation, data)
  if data.event == 'step' then 
    if part=='left_foot' then 
        play_sound('normal_foot_sound')
   elseif part=='right_foot' then 
        play_sound('wood_leg_sound') -- it is a pirate!
   end
    play_fx('dust')
  end
end

function init(self)
    local component = "#robot"
   self.id = go.get_id()
   self.weapon_url = msg.url('/weapon')
   self.weapon_collision = msg.url('/weapon#collision_object')
    -- Register a callback to a part (maybe allow a list of parts?)
    -- give component, the part name, the callback, and a context to pass to the callback
    -- last argument make the part invisible (not even rendered) so we can replace it with a gameobject (which itself has a sprite). But maybe we want to keep it, for example just attach an FX to it.
    spriteloop.register_callback(component, "weapon", weapon_callback,  self, true)
    spriteloop.register_callback(component, ["left_foot", "righ_foot"], footstep_callback,  self)

 --- now everytime we play an anim, the callbacks are called at each frame IF data for the specific part has changed
    spriteloop.play_anim(component, "attack", { loop = true })
end

With this setup, events could just be a string data in a keyframe for a part, like any other value (but never interpolated).

With this setup, the animation designer can add parts that will behave like an anchor in Defold, but with a mock graphic (it is easier to animate with a real size object!). It can add event name at specific frames (and parts) in the editor for timing of defold events, or saying “play a sound” or “activate FX” etc.
Then everything is handled by Defold in the callback, your extension doesn’t even need to know what it is doing.

This is just a mind experience for now, but with such API we can basically do anything! Maybe it is also missing a callback when the animation is finished, but should be a last argument in the play_anim() call I presume.

And I would finally be able to make the Fighting game I wanted to do, with handling hit and hurt boxes that follow animations! I started to create this kind of game once, but it was too hard to do it without a tool like you are building.

If you add all of that, it will be version 1.0 I guess :star_struck:

5 Likes

Really glad to hear v0.8 feels that much easier to use than v0.7.

And thank you for the support on itch as well. I really appreciate it.

Also, hearing that the tool is making you excited to work on your fighting game idea is probably one of the best kinds of feedback I can get :blush:

Yes, I agree the UX can probably be improved further. I implemented it this way because the Smart Limb parameters are not animatable, so in most cases you only need to configure them once, if at all.

All fields have tooltips on hover, though in general these are terms I borrowed from other animation software.

  • Influence controls how much the target control affects the limb.
  • Softness helps prevent knee/elbow popping by slowing down the limb as it approaches full extension.
  • Max Stretch is fairly straightforward and it limits how far the limb can stretch once the control moves beyond the limb’s natural length.
  • Stretch Falloff is a finer control that slows down the stretching as it approaches max stretch. It’s especially useful when transforms are interpolated, since it can reduce shaking in some cases when animating movement with only a few keyframes.

Events and attachment points are definitely on the todo list. I can only go down one rabbit hole at a time :grinning_face_with_smiling_eyes:

P.S. Cloud looks great in motion!

4 Likes

This sheet is dope! :smiley: :sweat_smile: (dopesheet wip)

Update:

12 Likes

@Mathias You can’t say I don’t listen. :wink: :up_arrow:

  • Multi-Select Inspector
  • New Dopesheet Mode

9 Likes

Wow! I already had complete confidence in your progress, but now I can’t even keep up to do the tests because it’s going so fast!

I will definitly make a new animation right now!

2 Likes

Hi! First of all, thank you for this software and for continuing to improve it!

I’ve run into an issue when working with small objects, for example 32×32 ones. If I want to move such an object, I first have to scale the view up. Otherwise, when I try to drag it, I end up clicking the pivot handles instead.

I tried locking the handles, but that doesn’t really solve the problem.

It would be great if there were a way to select a dedicated Move tool and use it independently from the pivot controls. Alternatively, having a separate move handle/gizmo for moving objects could also be very helpful.

1 Like

Hi! Thanks for giving it a try!

Indeed working with small parts is not the best expirience right now.

Locking the params in the inspector only prevents movement on the “axis”.

I can definitely do that! Thanks to the feedback!

1 Like

@Alexander_Bulatov

Something like this? It can be toggled with T. Also, locking the props will hide the handles.

I’m a bit stubborn about adding gizmos for now. I have a hard time aiming those tiny arrows.

P.S. You can also use arrow keys to move parts even now. And hold shift to move faster.

1 Like

There is also one more thing I noticed. After updating some graphics, the changes were not reflected in SpriteLoops. It would be nice to have an option to manually refresh or reload the graphics when needed after making changes.

2 Likes

Also, it would be really helpful to be able to duplicate an animation.
Another small quality-of-life improvement would be buttons to jump directly to the beginning or the end of an animation.

2 Likes

Yes, this is something Mathias also mentioned. I want to keep project files easily shareable, while still allowing a flexible workflow when source files get updated. I’ll probably introduce a “working directory” setting or something similar, on top of manual file/part replacement.

Noted!

Note GIFs | Tenor

1 Like

Cool! But I think right now we cant even replace the png of an already imported part?
Or I have miss this? If you re-import a png, it creates a new part no?

1 Like

Wow, this is amazing, man—I’m just starting to use this awesome tool.
It’s brought me back to Defold (I was stuck in the mess of Unity’s skeletal animation system).

Also, it would be great if it included color animation features (I often use white sprites and change their color at runtime) <3

Anyway, fantastic work, man.

3 Likes

True. I’m working on it. Shared some progress here: Refresh / Reload Graphics After External Changes · Issue #4 · Balkan-Ram-Games/spriteloop-defold · GitHub I probbaly have to create another repo for the app.

Thanks Kan!

I will try. It requires some changes to the defold extension. I may also add some blend modes when I’m there.

2 Likes