The delay of switching animation in the same sprite object.

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.