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 :)

Barry

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

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

Peach :)

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 :)

Barry

Barry - I'm fairly new with sprites but have used them a lot and never found a way to do that either...

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):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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

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 :)

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 ;)

End result: Likely I shall do both! Thanks.

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

Peach :)

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

    table.append(masterFrameList, anims)

should be

    table.append(masterFrameList, frames)

@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 :)

you could also just copy a sprite block in your sheet.lua and give it a different name while using the same textureRect etc.

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

greetings

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 :)

views:2153 update:2011/12/1 20:56:45
corona forums © 2003-2011