Creating a non-linear animation

I am trying to set up a load of animations, that use the same frames but in different orders, and so far I’ve not encountered a way of doing it.

The sprite.add() is limited to a linear set of frames, as in:

sprite.add( set, animName, firstFrame, frames, duration, loop )

So if a sprite set contains 10 frames, I can do animations of things such as 1-10, 3-7 etc, but nothing more adventurous, such as frames 7 then 6 then 5.

I *can* set up a new sprite set with frames in a different order, but this again goes wrong when I want to have an anim using repeated frames. EG assume I have a sprite set with 6 frames, and I want the following animations from it:

walk = 1, 2, 3, 4, 5, 6
run = 1, 3, 5
stutter = 1, 2, 3, 3, 3, 3, 4, 5, 6

there is no way I can do it (as far as I am aware).
Is there a way to create an animation passing a list of frames needed rather than just startFrame and frameCount to sprite.add() ?

This seems like a massive oversight if there is no way of doing it, and also silly, as it should be easy to do!

Hopefully I am wrong, so feel free to jump in and point out my silliness :slight_smile:

Barry [import]uid: 46639 topic_id: 18342 reply_id: 318342[/import]

It is possible to create a sprite that plays in the reverse direction :slight_smile:

Here’s a link that covers some of your options; http://developer.anscamobile.com/reference/sprite-sheets

Peach :slight_smile: [import]uid: 52491 topic_id: 18342 reply_id: 70284[/import]

Thanks, but I am aware of that (and mentioned it in my post).
I am looking at a way of tapping into the animation functions to run non-linear (frame order-wise) sequences, rather than have to write my own animation handler.
Take a look at the 3 examples I gave regarding frame order, and let me know (if possible) how you would do the “run” and “stutter” animations as they are written?

How about an alternative version of:

sprite.add( set, animName, firstFrame, frames, duration, loop )

where instead of specifying firstFrame and frames you pass a table? EG:

sprite.add( set, animName, tableOfFrames, duration, loop )

where in my examples above, tableOfFrames would be:

{1, 2, 3, 4, 5, 6} - for ´walk´
{1, 3, 5} - for ´run´
{1, 2, 3, 3, 3, 3, 4, 5, 6} - for ´stutter´

so I can do what I want.
Only being able to use frames in a hard-coded order is extremely limiting, and really, considering how easy it is to sort, should be fixed. Am just surprised I couldn’t find anyone running into the same problem, which is why I am wondering if I missed something :slight_smile:

Barry [import]uid: 46639 topic_id: 18342 reply_id: 70288[/import]

Barry - I’m fairly new with sprites but have used them a lot and never found a way to do that either… [import]uid: 40033 topic_id: 18342 reply_id: 70291[/import]

I have been tinkering around with my code and I believe I found a crude answer, but still not automatic as it should be (See the NOTE: bit below for pseudo code that gets around my problem).
Furthermore, it is counter-intuitive to the workflow and code that corona supplies, so I shall attempt to describe it here.

Corona documents suggest that you do the following:

  • Create a sprite sheet from an image (newSpriteSheet)
  • Split the sprite sheet into thematically related sprite sets. (newSpriteSet)
  • Create animations based on the sprite sets. (sprite.add)
  • Create sprites and change their animations as you see fit (newSprite, prepare, play, stop etc.)

To have proper flexibility, I have to do the following:

  • Create mutliple sprite sheets from an image, one per animation (newSpriteSheetFromData()
  • Assign a single default sprite set (newSpriteSet)
  • Create a single animation (sprite.add)
  • Create a sprite (newSprite), but to change animations you must delete it and create a new one since each animation now uses its own sprite sheet (despite sharing an image).

The key to getting repeated frames and frames out of sequence is to set up the SPRITE SHEET using newSpriteSheetFromData() instead of newSpriteSheet, as it allows you to chop up the sprite image into as many frames as you want, in any order. One assumes it does not actually split up the image itself, merely storing a set of appropriate UV coordinates (saving on texture memory)

NOTE: Thinking about what I just wrote, it would be possible to avoid the problem of the final step in my list above, but it does mean you can’t dynamically add animations.
This is not really a problem though, but it means a change in the order of the work, IE normally you’d define the sprite sheet, then the sets then the animations, but here you need to specify the animations before the sprite sheet.

The theory is that you would create a super table that contains all the animation frames appended. Since you can repeat frames, you then just need a way of tracking the information.

Pseudo code using my animation examples above might be something similar to (ignoring things like loop and duration for simplicity of viewing):

[code]masterFrameList = {}
anims = {}

defineAnim( “walk”, {1, 2, 3, 4, 5, 6})
defineAnim( “run”, {1, 3, 5})
defineAnim( “stutter”, {1, 2, 3, 3, 3, 3, 4})

sheet, set = createSpriteAndAnimations( anims, masterFrameList)


function defineAnim( animName, frames)

firstFrame = #masterAnim + 1
totalFrames = #frames

anims[animName] = [firstFrame, totalFrames]
table.append(masterFrameList, anims)

end


function createSpriteSheetAndAnims( anims, masterFrameList )

– Build up sprite sheet frame data from the masterFrameList, however you deem appropriate)
framesData = {}…
spriteSheet = sprite.newSpriteSheetFromData(framesData)

– Create single sprite set
spriteSet = sprite.newSpriteSet(spriteSheet, 1, #framesData)

– Create the animations
for k,v in pairs(anims) do
sprite.add( spriteSet, k, v[1], v[2], duration, loop)
end

– Return the data
return spriteSheet, spriteSet

end[/code]

As you can see it isn’t that tough to do, but flies in the face of the sheet->set->anims logic that corona implements.

So, for now, I believe I can do what I want, and that at least makes me happy, but it clearly isn’t intuitive, and will require a fair amount of code, and assuredly it comes with a memory overhead (how much remains to be seem, hopefully negligible).

Barry [import]uid: 46639 topic_id: 18342 reply_id: 70297[/import]

Apologies, your line; “but nothing more adventurous, such as frames 7 then 6 then 5.” made me think you were unaware of the ability to reverse the order.

If this feature is important to you I’d encourage you to make a post in Feature Requests. (We have two feature request forums, please use the subscribers only one.)

Peach :slight_smile: [import]uid: 52491 topic_id: 18342 reply_id: 70304[/import]

Thanks, I will when I get time.
Thing is, if I have that time, I can probably whip up my pseudo-code into a module which would would be a much quicker result :wink:

End result: Likely I shall do both! Thanks. [import]uid: 46639 topic_id: 18342 reply_id: 70306[/import]

No worries, sorry for the misunderstanding - your workaround is quite impressive!

Peach :slight_smile: [import]uid: 52491 topic_id: 18342 reply_id: 70309[/import]

Tis only pseudo code, but I still noticed a theoretical bug. The line:

 table.append(masterFrameList, anims)

should be

 table.append(masterFrameList, frames)

[import]uid: 46639 topic_id: 18342 reply_id: 70331[/import]

@rakoonic:

I use to do it this way:

first, i do one single spritesheet with all frames, with the help of texture packer. it will generate me the spritesheet.

after that, in your example:

walk = 1, 2, 3, 4, 5, 6
run = 1, 3, 5
stutter = 1, 2, 3, 3, 3, 3, 4, 5, 6

i would create 3 different spriteSheets walk, run, stuter. each of them using the same spritesheet.png BUT different spriteSheetData.lua files. in the .lua file, i set the correct frame order (e.g walk, 1,2,3,4,5,6).

then i simply load the corresponding spritesheetdata into the spriteset, load the sprite and you are done.

EDIT: i have just seen your workaround. but still my two cents without workaround :slight_smile: [import]uid: 90610 topic_id: 18342 reply_id: 70348[/import]

you could also just copy a sprite block in your sheet.lua and give it a different name while using the same textureRect etc. [import]uid: 70635 topic_id: 18342 reply_id: 70354[/import]

@canupa: yes, that’s what i wanted to tell, i am doing it always like that. not a big deal.

greetings [import]uid: 90610 topic_id: 18342 reply_id: 70356[/import]

I’ve never bothered with texture packer - I only use evenly sized tiles, so I have just written my own wrapper for sprite.newSpriteSheetFromData (I now never use newSpriteSheet).

Glad it works for you guys, and means at least I am on the right path :slight_smile: [import]uid: 46639 topic_id: 18342 reply_id: 70407[/import]

Peach - you stated:
Apologies, your line; “but nothing more adventurous, such as frames 7 then 6 then 5.” made me think you were unaware of the ability to reverse the order.

How do you do this, IE run a single animation in reverse? The only thing I can find close to this is the -1 and -2 loop parameters in sprite.add(), but that isn’t in reverse order, it is a ping-pong effect playing forwards then reverse afterwards.
I actually do want to do something in reverse, so would appreciate the help or I am going to have to write some more code again… :frowning: [import]uid: 46639 topic_id: 18342 reply_id: 70751[/import]

OK getting a bit bloody annoyed at the apparent stupid limitations in the sprite stuff.

Am I going mad or is there a minimum playback speed that I cannot drop below no matter what value I stick in ‘duration’ in sprite.add(), or scale up with sprite.timeScale?

I have a 20 frame animation of an arm throwing an object and I can’t for the life of me get it to go fast enough to look realistic.

Is it the case that regardless of duration / timeScale etc, that an animation can’t go any faster than 1 frame of animation update per screen refresh? IE I have 30 fps set in my config, so the minimum speed is 2/3rds of a second (for my 20 frame anim)? [import]uid: 46639 topic_id: 18342 reply_id: 70760[/import]

Reverse playback option has all the details here; http://blog.anscamobile.com/2010/06/improved-movieclip-library/

It uses the improved movieclip library :slight_smile:

As to the last part of your post - no, you cannot update images more times than the number of “refreshes” per second, which in your case you have decided to cap at 30.

How did you come to 2/3rds of a second using 30 FPS?

Peach [import]uid: 52491 topic_id: 18342 reply_id: 70771[/import]

Heh no offence Peach, I appreciate you trying to help really I do, but movieclips have the performance of a dead dog - one of the first things I did when I picked up Corona was realise I needed to ditch movieclips for sprite sheets and never touch them again :slight_smile:

The 2/3rds of a second was easy, and specific to the example I gave. I have a 20 frame animation at 30 frames per second, hence it will take a minimum of 2/3rds of a second to play the animation.

I tried to file this behaviour as a bug (and it *is* a bug), and then got frustrated by the bug system, so for now it is purely in the bug forum. [import]uid: 46639 topic_id: 18342 reply_id: 70774[/import]

Movieclip performance really depends on a number of things and in some cases can be very useful, although I do not agree a “normal” sprite is typically better.

Either way, I’ve passed on your other thread to the rest of the team.

Peach :slight_smile: [import]uid: 52491 topic_id: 18342 reply_id: 70802[/import]

Movieclips do have certain benefits - they are easier to set up, are more flexible etc. I agree (I have my own button / interface routines that use the same idea of having a container group and toggling individual images).

However, their limitations are widely known (although, IMO, under-recognised) so for anything remotely performance critical, they are to be avoided.

I did some speed test comparisions ages ago for a scrolling tile map, and I don’t recall exactly, but it was something like on my old ipod touch, with 48x48 tiles, the difference between 40 fps (sprite sheets) and 5 fps (not movie clips, but using the same image swapping logic - bear in mind this means my code was more optimised than movie clips are!).

But anyway, again I appreciate your continued help on this :slight_smile:
I discovered the issue far too late into this project for me to wait for a solution, so I will have to write my own animation code, but it would be nice to not have this problem in the future. [import]uid: 46639 topic_id: 18342 reply_id: 70836[/import]