Regression bug: Dynamically setting spriteObject.timeScale causes skipped frames

Corona SDK: 2013.1157

I’m converting one of my apps from the deprecated sprite.* API to the new API and have run into a regression bug.

Dynamically setting object.timeScale works fine in the old API, but skips frames in the new one.

I have a sprite-object with 5 frames where the timeScale is set depending on how fast the object is moving. The timeScale is calculated in the onSpriteEvent handler on each “loop” event.

The weird thing is that the frame skipping only occurs if the timeScale value changes between calls. If it remains the same between calls, no frame skipping occurs.

Here’s a dump from the onSpriteEvent handler when the speed is changing. The frames should progress from frame 1 to 5 in sequential order, but as you can see, some frames are skipped after changing the timeScale.

loop    1    

1    goalieblue    loop    setspeed     0.82054866790771    

next    5    

loop    1    

1    goalieblue    loop    setspeed     0.73574411392212    

next    4    

next    5    

loop    1    

1    goalieblue    loop    setspeed     0.62053208351135    

next    3    

next    4    

next    5    

loop    1    

1    goalieblue    loop    setspeed     0.71538330078125    

next    4    

next    5    

loop    1    

1    goalieblue    loop    setspeed     0.6395166683197    

next    3    

next    4    

next    5    

loop    1    

1    goalieblue    loop    setspeed     0.66574281692505    

next    2    

next    3    

next    4    

next    5    

loop    1    

1    goalieblue    loop    setspeed     0.70823823928833    

next    3    

next    4    

next    5    

…and here’s a dump when timeScale is set to the *same* value on every call. No frame skipping occurs.

loop    1    

1    goalieblue    loop    setspeed     0.5    

next    2    

next    3    

next    4    

next    5    

loop    1    

1    goalieblue    loop    setspeed     0.5    

next    2    

next    3    

next    4    

next    5    

loop    1    

1    goalieblue    loop    setspeed     0.5    

next    2    

next    3    

next    4    

next    5    

loop    1    

1    goalieblue    loop    setspeed     0.5    

next    2    

next    3    

next    4    

next    5    

Any advice would be appreciated.

I managed to get around the problem by storing the frame number before setting timeScale, and then setting the frame back to the stored value.

Something like this:

local frame = player.frame; player.timeScale = (abs(vy)/100) + 0.5; player:setFrame(frame);

Hi Ingemar,

Are you sure this is a regression issue? I think this is the way it has always worked. Do you specifically remember that it worked differently in the old “sprite” library? Personally, I’ve always used it like you are now: reading the frame first, changing the time scale, and setting the frame again.

Regards,

Brent

Yeah, I’m sure about it.

I have an app on the Apple and Google Play store which was released in 2011, and it has not shown this behavior.

I was changing the timeScale without storing/setting the current frame. Over the years I’ve had about a dozen updates as well, and all of them have behaved as expected.

The reason why I noticed it now was because I’m updating my code to use Image sheets and the new API. After changing to the new API I immediately saw the frame skipping behavior.

It’s good to know that I’m now using ‘best practices’ to change the timeScale.

I think it would be a good idea to mention this fact in a ‘Gotchas’ section of the timeScale documentation as it’s not too obvious having to store/set the sprite frame between calls.

Hi Ingemar,

I just filed a bug report and test case for this. It shouldn’t be necessary to get/set the frame between timeScale switches. I don’t know how fast this bug will be fixed since timeScale isn’t a widely-used API, but at least now it’s in the system.

Bug case is #24946. Thanks for bringing it to my attention.

Brent

I managed to get around the problem by storing the frame number before setting timeScale, and then setting the frame back to the stored value.

Something like this:

local frame = player.frame; player.timeScale = (abs(vy)/100) + 0.5; player:setFrame(frame);

Hi Ingemar,

Are you sure this is a regression issue? I think this is the way it has always worked. Do you specifically remember that it worked differently in the old “sprite” library? Personally, I’ve always used it like you are now: reading the frame first, changing the time scale, and setting the frame again.

Regards,

Brent

Yeah, I’m sure about it.

I have an app on the Apple and Google Play store which was released in 2011, and it has not shown this behavior.

I was changing the timeScale without storing/setting the current frame. Over the years I’ve had about a dozen updates as well, and all of them have behaved as expected.

The reason why I noticed it now was because I’m updating my code to use Image sheets and the new API. After changing to the new API I immediately saw the frame skipping behavior.

It’s good to know that I’m now using ‘best practices’ to change the timeScale.

I think it would be a good idea to mention this fact in a ‘Gotchas’ section of the timeScale documentation as it’s not too obvious having to store/set the sprite frame between calls.

Hi Ingemar,

I just filed a bug report and test case for this. It shouldn’t be necessary to get/set the frame between timeScale switches. I don’t know how fast this bug will be fixed since timeScale isn’t a widely-used API, but at least now it’s in the system.

Bug case is #24946. Thanks for bringing it to my attention.

Brent