Flash Rotation Bug (with Fix)
I recently ran into a nasty “little” bug in Flash that happened to eat up a “big” chunk of my time. I’m surprised I haven’t heard more about this particular bug since the conditions which cause it would seem fairly common.
Let’s say you’re using an onEnterFrame event to count frames as they pass with code like this:
//
var count = 0;
onEnterFrame = function(){
count++;
}
//
//
Now let’s suppose we want to rotate an arrow 1 degree every time a frame passes. We could write code like the following:
//
var count = 0;
onEnterFrame = function(){
count++;
Arrow._rotation = count;
}
//
//
That code works fine up to a point but for some reason, after 91 full rotations Flash no longer correctly positions the arrow. Flash reports the correct angle of rotation but the arrow will be placed 16 degrees behind where Flash ~claims~ it to be!
To better isolate the exact moment where things go wrong I have changed the onEnterFrame event to an onMouseDown event and set the counter to start at 91 full rotations (91 X 360 = 32,760). Click the SWF file below 9 times to see the error reproduced at 32,768 and press any key to reset.
Once the arrow reaches 32,768 degrees of rotation, the arrow graphic jumps back from 8 degrees to -8 degrees even though it's rotation is correctly reported as 8 degrees. From this point on, the arrow graphic will always be 16 degrees behind where it is supposed to be.
If you continue the process the errors accumulate and the arrow gets further and further out of sync. In the following file I add 361 to count (rather than 1) to accelerate the process.
As you can see, even though I'm setting the green arrow to match the black arrow's rotation, the two definitely do not coincide. Of the two, the green arrow is the one that is properly positioned.
You can reproduce this bug with code similar to the following:
//
var count = 0;
onEnterFrame = function(){
count += 361;
BlackArrow._rotation = count;
GreenArrow._rotation = BlackArrow._rotation;
Display.text = "Count = "+count;
Display.text += "\nArrow._rotation = "+Arrow._rotation;
}
//
//
WorkAround Solution: Fortunately there's a simple fix for this Flash bug. Rather than letting Flash convert 32,768 degrees of rotation to 8 degrees, do it yourself and make sure it gets done right. Use the modulo operator to guarantee that the arrow is really where Flash tells you it is by setting the black arrow's rotation with code like this:
//
BlackArrow._rotation = count %360;
//
//
I hope this tip saves you some time and frustration.
Thanks so much for posting this. Yours was the ONLY link describing this issue that google pulled up, and if it weren’t for you guys, I would never have known what was causing my flash to break.
Thanks, Jared
[…] also posted more details about this bug. The solution is simple: Use modulo within the enterFrameHandler to assign proper […]
@Ophi, If rotation is a signed “integer”, wouldn’t that mean _rotation doesn’t hold fractional values? I’m pretty sure _rotation can be set to decimal values like 22.5.
Hi. 32767 is the max number of the signed integer type. (2 bytes, with first bit for the sign). I think _rotation is simply a signed integer going from -32768 to 32767. So when you try to assign it a value greater than 32767, all the bits don’t fit into this signed integer, and so there is the bug. To avoid that, you must increment _rotation and not count.
_rotation+=361
(flash will implicitely do the trick)
Hey, works fine with AS2 🙂
Sorry Laurence, I haven’t a clue. Using modulo should yield results like “358, 359, 0, 1, 2” not “358, 359, 360, 0, 1, 2″, if that helps at all.
this is really bad! i’m setting the rotation of an object using Tween class. I my object to turn an infinate number of times continuously. The problem with using the modulous hack is that it will make the objec t rotate, 358, 359, 360, 0, 1, 2 degrees. But if this is tweened, the object will spin:
358 [clockwise] 359 [clockwise] 360 [clockwise] 0 [COUNTER-clockwise] 1 [clockwise] 2 [clockwise]
it looks so stupid! and ideas?
I understand that Flash returns values between -180 and 180 degrees, that “correct” value is what’s properly positioning the green arrow in the second SWF.
Although the -180 to +180 may have something to do with the juxtaposition of -8 and +8, I think the fact that the error is 16 degrees apart (2 to the 4th power) and the fact that the error occurs precisely at 32,768 degrees (2 to the 15th power) is more notable.
Somebody at Flash HQ probably messed up their ‘maths’. 😀
I think that’s because “rotation” increases up to 180 and then begins counting down and in the negative
0
1
…
179
180
-179
-178
…
-1
0
1
etc
etc
etc
Why Flash breaks it after 91 revolutions is bizarre though…
🙂