The delay of switching animation in the same sprite object.

Hi, 

I read the document below and I know I can switch the animation in the same sprite object with 

the object:setSequence() and the object:play()

https://docs.coronalabs.com/api/type/SpriteObject/index.html

Does the animation change immediately after the object:play() or it will delay 1 frame?

This question is a little unclear.  Do you mean:

Case 1 - Single Frame Delay

  • Frame 10 - Called setSequence() followed by play()
  • Frame 11 - No change
  • Frame 12 - Change seen

versus

Case 2 - No Frame Delay

  • Frame 10 - Called setSequence() followed by play()
  • Frame 11 - Change seen

or is this what you consider a no frame delay:

Case 3 - Same Frame

  • Frame 10 - Called setSequence() followed by play() —> Change seen

I’m pretty sure what you should see is case 2.

As I understand the sequencing, by the time your code is executing, the frame is drawn, so changes won’t take  affect till the next draw cycle.

PS - Frame in all contexts above is a Corona frame, not a animation frame.  While animation frames align with Corona frames, I’m discussing one Corona rendering frame, followed by the next, followed by the next, and so on.

Thank you for the replay.

 

How about the following cases?

  • Case 4

  • Frame 10 - setSequence() -> play(), The new sequence is played but the change has not seen.

  • Frame 11 - Change seen and the new sequence has already be played for 1 frame.

  • Case 5

  • Frame 10 - setSequence() -> play(), The new sequence does not be played and the change has not seen.

  • Frame 11 - Change seen and the new sequence just started to be played.

I don’t understand… case 4 and 5 are the same as case 2

If the game is 60fps and each animation frame duration is 100ms.

Case 4

 F10                                                                F11  

   |                                                                       |                    

play()

first frame drawn                                    first frame shown

first frame remained 100ms                   first frame remained 100 - 16ms

Case 5

 F10                                                                F11                                              F12

   |                                                                       |                                                   |

play()

first frame drawn                                    first frame shown

first frame remained 100ms                   first frame remained 100ms             first frame remained 100-16 ms

I’ve lost the track of this discussion.

Clearly you’ve run into a problem.  

I think you are having an issue and are assuming it is related to how sprites work, when it might be your usage or assumptions. 

It is better to do the following instead:

  1. Tell us what you did.

  2. Tell us what you saw.

  3. Tell us why you think it is wrong.

  4. Tell us what you did to debug it.

EVEN BETTER… If you can replicate your issue in a TINY example (just main.lua and assets) then do so and share it as a zip file attachment here, along with 1…4 above.

PS - I’m pretty sure the first frame is NOT drawn in the same frame you call play() as show above, since everything for that frame has already been drawn by the time you call play()

@roaminggamer is right, we need a better example, preferably a sample project to help see what you’re seeing.  However, I will add this: 60 fps = 16.667ms per frame and not guaranteed.  100ms frame update on your animation will on frame 6 if we are hitting 60fps exactly. If there are computational delays that slow down our updates, it might be frame 7 before the next visual sprite update happens.

But it sounds like you’re “losing” an animation frame somewhere. And that sample project will give people like @roaminggamer an idea as to what’s going on.

Rob

Hi, 

Thank you for the reply again.

What I want to do is to concatenate every animation sequence “smoothly”. It means the new sequence should be played immediately after the play().

I’m very confused about the animation switching and I made a sample here:

https://www.dropbox.com/s/puy1jioj12u8m0d/spritesheetdemo.zip?dl=0

This sample has 5 sequences, 30fps, and the duration of each animation frame is 100ms. 

I added the event listener to the sprite object so that I can switch to the next animation when the previous sequence is ended. 

I also printed every sprite event and the time difference.

catch event:    sprite   /  next    :   99.53

catch event:    sprite   /  next    :   98.892

catch event:    sprite   /  next    :   98.102

catch event:    sprite   /  next    :   99.771

catch event:    sprite   /  next    :   97.855

catch event:    sprite   /  ended   :   99.68

catch event:    sprite   /  began   :   33.379

catch event:    sprite   /  next    :   99.196

catch event:    sprite   /  next    :   99.024

catch event:    sprite   /  next    :   98.64

catch event:    sprite   /  next    :   98.574

catch event:    sprite   /  next    :   99.765

catch event:    sprite   /  next    :   99.013

I exepected the new sequence should be played immediately after I called the play(). But it seems like it’ll delayed 1 corona frame.

Are you saying you expected this?:

catch event:    sprite   /  next    :   97.855

catch event:    sprite   /  ended   :   99.68

catch event:    sprite   /  began   :   0

catch event:    sprite   /  next    :   99.196

If so, that is a wrong understanding of how this works and how and when your measurement code runs.

~

First, By the time your script is running, all rendering for the current frame is done.  No more rendering will occur till all scripts are done executing and control is handed back to Corona.

Second, when you call play(), it doesn’t do anything till the next rendering time (beginning of next frame). 

Third, no events will be triggered till the began action takes effect.

Fourth, triggered events are processed by your scripts in the next available frame.

So, the delay 33.xxx ms you see is the time between when your script called play() and the next frame when the event listener printed the elapsed time till the began event got processed

The began() call take effect between those two times (again, at the beginning of the frame in which the message is printed)

| Frame 10                                   

| physics processing, internal stuff, rendering … SCRIPTS=> … play()called … FRAME ENDS

| Frame 11

| physics processing, internal stuff, rendering … SCRIPTS=> … sprite listener …  FRAME ENDS

                      */* play() takes effect somewhere in here

Note:… is time elapsing 

PS - I might very well have this flip-flopped.  SCRIPT PROCESSING MIGHT BE FIRST, THEN INTERNAL STUFF.  The key takeaway is that they should be considered separated as two sub-parts of a frame.

I ran this and don’t see any problems.  I think you’re simply misinterpreting things a little.  play() is taking effect as soon as it can, which is near the beginning of the next frame.  I say near, because there may be other work stacked up before it since you don’t control work ordering entirely.

Note: The only issues you’ll run into is when an animation duration doesn’t line up nicely with a frame period.  The simplest way to solve this is to use the fps =  60 setting in config.lua 

The period for 30 FPS is approximately 33.33 ms -> in reality more like 33 or 34 ms

The period for 16 FPS is approximately 16.66 ms -> in reality more like 36 or 17 ms

So for a 100ms animation frame, you’d probaly see something like this (assuming low realistic values)

@ 30 FPS=> action         | began animation                | ended animation; start next frame

           elapsed time   | 0 … 33 … 66 … 99 … 132 | 

@ 60 FPS=> action         | began animation                                    | ended, etc.

           elapsed time   | 0 … 16 … 32 … 48 … 64 …80 … 96 … 112 | 

Yes, the animation in the script “look” well.

 

So I expected the time difference between began event and the followed next event should be less one corona frame:

 

catch event:    sprite   /  next    :   99.53

catch event:    sprite   /  next    :   98.892

catch event:    sprite   /  next    :   98.102

catch event:    sprite   /  next    :   99.771

catch event:    sprite   /  next    :   97.855

catch event:    sprite   /  ended   :   99.68

catch event:    sprite   /  began   :   33.379

catch event:    sprite   /  next    :   66 ( 99 - 33)

catch event:    sprite   /  next    :   99.024

catch event:    sprite   /  next    :   98.64

catch event:    sprite   /  next    :   98.574

catch event:    sprite   /  next    :   99.765

catch event:    sprite   /  next    :   99.013

 

But it’s not…

First, I should say.  Thus far I’m very happy with this thread.  I really appreciate the quality of it and the fact that you created a project too.

This is one of the top posts I’ve answered (or tried to answer) in quite some time.

Second, I don’t know what is going on here and I need to think about it a bit.  To help myself I re-wrote your example with a simpler sprite sheet and more basic animation sequences.  I’m attaching it in case it is helpful to anyone else who is trying to figure this out with us.

My animation is just three identical sequences showing 5 frames over a period of 500 ms.  A, B, … E

I also modified the listener and output such that it shows the current frame number of the animation, a rounded delta time, and it destroys the object 300 ms after the second animation.  This gives just enough output to dig around and think about the behavior.

I will continue to think about this, but right now I don’t have a solid answer for you.

11:01:23.674  -----------------------------------

11:01:23.674  anim frame: 01 dt: 1 phase: began

11:01:23.674  anim frame: 02 dt: 104 phase: next

11:01:23.674  anim frame: 03 dt: 95 phase: next

11:01:23.674  anim frame: 04 dt: 93 phase: next

11:01:23.674  anim frame: 05 dt: 122 phase: ended

11:01:23.674   scheduled remove @ 422.2

11:01:23.674  -----------------------------------

11:01:23.674  anim frame: 01 dt: 31 phase: began

11:01:23.674  anim frame: 02 dt: 93 phase: next

11:01:23.674  anim frame: 03 dt: 78 phase: next

11:01:23.674  anim frame: 04 dt: 124 phase: next

11:01:23.674   removing @ 748

From what I can tell, the last frame of each animation is not playing.  

You can see this if you go to line 67 and by  changing the ‘timeScale’ to 0.2.  Notice that E is never shown.

@roaminggamer
 
Thank you for minifying the project so that we can find the problem more easier.
 
I made a mistake in my lastest project.
 
I thought the ended event will be fired when the animation was ended. But in fact the ended event will be fired when the ended frame started to be played.
 
This is why the last frame is not playing.
 
In order to solve the problem, I put the setSequence() and the followd play() into the delay callback.
 

https://www.dropbox.com/s/79f1gzrrkfk2syj/simpler%202.zip?dl=0

This is the output of the new sample in the first 5 loops:
 

anim frame: 01 dt: 1 phase: began
anim frame: 02 dt: 33 phase: next
anim frame: 03 dt: 34 phase: next
anim frame: 04 dt: 99 phase: next
anim frame: 05 dt: 99 phase: ended
 scheduled to play next sequence @ 405.595
 play next sequence @ 537.564
 

anim frame: 01 dt: 165 phase: began
anim frame: 02 dt: 99 phase: next
anim frame: 03 dt: 100 phase: next
anim frame: 04 dt: 99 phase: next
anim frame: 05 dt: 99 phase: ended
 scheduled to play next sequence @ 967.089
 play next sequence @ 1098.505
 

anim frame: 01 dt: 165 phase: began
anim frame: 02 dt: 66 phase: next
anim frame: 03 dt: 131 phase: next
anim frame: 04 dt: 100 phase: next
anim frame: 05 dt: 99 phase: ended
 scheduled to play next sequence @ 1528.24
 play next sequence @ 1660.214
 

anim frame: 01 dt: 165 phase: began
anim frame: 02 dt: 107 phase: next
anim frame: 03 dt: 91 phase: next
anim frame: 04 dt: 99 phase: next
anim frame: 05 dt: 98 phase: ended
 scheduled to play next sequence @ 2088.037
 play next sequence @ 2188.228
 

anim frame: 01 dt: 132 phase: began
anim frame: 02 dt: 99 phase: next
anim frame: 03 dt: 99 phase: next
anim frame: 04 dt: 99 phase: next
anim frame: 05 dt: 99 phase: ended
 scheduled to play next sequence @ 2617.246
 play next sequence @ 2749.297
 
What I expected is the animaton A -> B -> C -> D -> E -> A -> B -> … between sequences will be looped smoothly. 
 
But the first frame in each sequence seems to be delayed for 1 or 2 corona frame in the new sample because of the timer.

This question is a little unclear.  Do you mean:

Case 1 - Single Frame Delay

  • Frame 10 - Called setSequence() followed by play()
  • Frame 11 - No change
  • Frame 12 - Change seen

versus

Case 2 - No Frame Delay

  • Frame 10 - Called setSequence() followed by play()
  • Frame 11 - Change seen

or is this what you consider a no frame delay:

Case 3 - Same Frame

  • Frame 10 - Called setSequence() followed by play() —> Change seen

I’m pretty sure what you should see is case 2.

As I understand the sequencing, by the time your code is executing, the frame is drawn, so changes won’t take  affect till the next draw cycle.

PS - Frame in all contexts above is a Corona frame, not a animation frame.  While animation frames align with Corona frames, I’m discussing one Corona rendering frame, followed by the next, followed by the next, and so on.

Thank you for the replay.

 

How about the following cases?

  • Case 4

  • Frame 10 - setSequence() -> play(), The new sequence is played but the change has not seen.

  • Frame 11 - Change seen and the new sequence has already be played for 1 frame.

  • Case 5

  • Frame 10 - setSequence() -> play(), The new sequence does not be played and the change has not seen.

  • Frame 11 - Change seen and the new sequence just started to be played.

I don’t understand… case 4 and 5 are the same as case 2

If the game is 60fps and each animation frame duration is 100ms.

Case 4

 F10                                                                F11  

   |                                                                       |                    

play()

first frame drawn                                    first frame shown

first frame remained 100ms                   first frame remained 100 - 16ms

Case 5

 F10                                                                F11                                              F12

   |                                                                       |                                                   |

play()

first frame drawn                                    first frame shown

first frame remained 100ms                   first frame remained 100ms             first frame remained 100-16 ms

I’ve lost the track of this discussion.

Clearly you’ve run into a problem.  

I think you are having an issue and are assuming it is related to how sprites work, when it might be your usage or assumptions. 

It is better to do the following instead:

  1. Tell us what you did.

  2. Tell us what you saw.

  3. Tell us why you think it is wrong.

  4. Tell us what you did to debug it.

EVEN BETTER… If you can replicate your issue in a TINY example (just main.lua and assets) then do so and share it as a zip file attachment here, along with 1…4 above.

PS - I’m pretty sure the first frame is NOT drawn in the same frame you call play() as show above, since everything for that frame has already been drawn by the time you call play()

@roaminggamer is right, we need a better example, preferably a sample project to help see what you’re seeing.  However, I will add this: 60 fps = 16.667ms per frame and not guaranteed.  100ms frame update on your animation will on frame 6 if we are hitting 60fps exactly. If there are computational delays that slow down our updates, it might be frame 7 before the next visual sprite update happens.

But it sounds like you’re “losing” an animation frame somewhere. And that sample project will give people like @roaminggamer an idea as to what’s going on.

Rob