Starting Sprite Animation From Random FrameIndex

Hi guys,

I have 35 frames in my sprite.

I want to start and stop sprite (frames) from a random frame index number, with animation. The nearest I could find is the function ‘object:setFrame()’, but if I use this, there won’t be any animation

For example, animate from frame #3 to frame #8.

The only possibility that I can think of is creating a lot of sprite ‘sequenceData’, which isn’t that practical.

Please advise.

Thanks

Hi @yosu,

I don’t understand what you mean by “there won’t be any animation” after you set a frame. It’s true that it won’t just automatically play, but the natural course is to always play() the sprite after setting a frame.

Brent

My main aim is to have a random start frame, and a random end frame. Multiple times (after random time delay) on the same sprite object.

For example, on sprite#1 :

start frame : 1

end frame : 5

– after 1 or 2 seconds

start frame : 6

end frame : 11

and so on after time.

If I use ‘setFrame(5)’ and ‘setFrame(11)’, then it will just jump to that frame (no animation).

OK, this might be a little extra effort but you can still avoid making a huge amount of sequences, and achieve your “random” method:

  1. Pick a random frame, use “mySprite:setFrame()” to go there.

  2. Pick a random end frame; set that value as a property on the sprite, i.e. “mySprite.endFrame” ( CAREFUL! I assume you have a reliable way to ensure this frame is after the starting frame and that it’s not higher than the total number of possible frames).

  3. Add a sprite listener to the sprite as shown in the “Sprite Events” section of our guide.

  4. Start playing the sprite using “mySprite:play()”.

  5. Inside the sprite listener function, detect the “event.phase” value of “next” ( CAREFUL! This could also be “ended” if your randomly chosen end frame is the last frame in the entire series!).

  6. On that event, check if the frame number (event.target.frame) is equal to the end frame value you set above (event.target.endFrame).

  7. If true, take action… in your case, I think it would just be to pause the animation with “mySprite:pause()”.

  8. After 1-2 seconds (however you do this, I assume a timer), repeat this proces from 1-8. Done! :slight_smile:

Hope that solves it!

Brent

Minor clarification: it’s probably obvious enough, but you only need to set up the sprite listener once.

So more accurately, you should do step 3 first (and only once). Then do steps 1-2, then 4-8, and repeat.

Thanks Brent.

This is how I implemented it :

-- Set the '.c\_stopFrame' and/or '.c\_startFrame' somewhere. This value must be in a table, as it is always updated (pass by reference) -- Remember, frame number will default to 1 as mentioned above. -- This call was done at another location; sprite:addEventListener( "sprite", spriteListener ) spriteInstance:setFrame( spriteInstance.c\_startFrame ) spriteInstance:play() spriteListener = function( event ) print( event.name, event.phase, event.target.frame ) local tmpCurrentSpriteFrame = event.target.frame -- The old deprecated method was using 'event.sprite' if event.target.c\_stopFrame == tmpCurrentSpriteFrame then event.target:pause() end end

Hi @yosu,

I don’t understand what you mean by “there won’t be any animation” after you set a frame. It’s true that it won’t just automatically play, but the natural course is to always play() the sprite after setting a frame.

Brent

My main aim is to have a random start frame, and a random end frame. Multiple times (after random time delay) on the same sprite object.

For example, on sprite#1 :

start frame : 1

end frame : 5

– after 1 or 2 seconds

start frame : 6

end frame : 11

and so on after time.

If I use ‘setFrame(5)’ and ‘setFrame(11)’, then it will just jump to that frame (no animation).

OK, this might be a little extra effort but you can still avoid making a huge amount of sequences, and achieve your “random” method:

  1. Pick a random frame, use “mySprite:setFrame()” to go there.

  2. Pick a random end frame; set that value as a property on the sprite, i.e. “mySprite.endFrame” ( CAREFUL! I assume you have a reliable way to ensure this frame is after the starting frame and that it’s not higher than the total number of possible frames).

  3. Add a sprite listener to the sprite as shown in the “Sprite Events” section of our guide.

  4. Start playing the sprite using “mySprite:play()”.

  5. Inside the sprite listener function, detect the “event.phase” value of “next” ( CAREFUL! This could also be “ended” if your randomly chosen end frame is the last frame in the entire series!).

  6. On that event, check if the frame number (event.target.frame) is equal to the end frame value you set above (event.target.endFrame).

  7. If true, take action… in your case, I think it would just be to pause the animation with “mySprite:pause()”.

  8. After 1-2 seconds (however you do this, I assume a timer), repeat this proces from 1-8. Done! :slight_smile:

Hope that solves it!

Brent

Minor clarification: it’s probably obvious enough, but you only need to set up the sprite listener once.

So more accurately, you should do step 3 first (and only once). Then do steps 1-2, then 4-8, and repeat.

Thanks Brent.

This is how I implemented it :

-- Set the '.c\_stopFrame' and/or '.c\_startFrame' somewhere. This value must be in a table, as it is always updated (pass by reference) -- Remember, frame number will default to 1 as mentioned above. -- This call was done at another location; sprite:addEventListener( "sprite", spriteListener ) spriteInstance:setFrame( spriteInstance.c\_startFrame ) spriteInstance:play() spriteListener = function( event ) print( event.name, event.phase, event.target.frame ) local tmpCurrentSpriteFrame = event.target.frame -- The old deprecated method was using 'event.sprite' if event.target.c\_stopFrame == tmpCurrentSpriteFrame then event.target:pause() end end