x and y precision in ActionScript 3
I ran into some strange behavior while programming zombies in ActionScript 3 this morning. The code was pretty straight-forward, setting the zombie sprite’s x and y in an enter frame loop to move it to some arbitrary point. As part of the loop, I was checking if the sprite’s rotation was equal to the angle between the sprite’s x and y coordinates and the target x and y coordinates:
// calculate the distance delta = new Point( point.x - zombie.x, point.y - zombie.y ); // calculate the correct rotation rotation = Math.atan2(delta.y, delta.x); rotation = radiansToDegrees(rotation); if(Math.round(rotation - zombie.rotation)) { // the difference between the zombie's // current rotation and the correct // rotation is greater than 1 degree, // so the zombie should rotate } else { // the zombie should move }
Unfortunately, the condition was behaving strangely, with Math.round(rotation - zombie.rotation) returning all sorts of values from 10° to -10° when it should have been returning 0°.
After some digging, I found the culprit: the x and y values of DisplayObject instances get floored to the nearest 0.05 of a pixel, which at small distances changes the angle returned by Math.atan2() by as much at 10°!
Here’s a simple test that creates a random number (i.e. a number with a lot of digits), and assigns the value to a sprite’s rotation, x and y properties, then traces out the values:
var value:Number = Math.random(); var sprite:Sprite = new Sprite(); sprite.rotation = value; sprite.x = value; sprite.y = value; trace(value, sprite.rotation, sprite.x, sprite.y);
And here are the results of a few test runs:
#value #sprite.rotation #sprite.x #sprite.y 0.26101896446198225 0.26101896446198225 0.25 0.25 0.5711805005557835 0.5711805005557835 0.55 0.55 0.3452326194383204 0.3452326194383204 0.3 0.3 0.1578897968865931 0.1578897968865931 0.15 0.15 0.7958266129717231 0.7958266129717231 0.75 0.75 0.1891973023302853 0.1891973023302853 0.15 0.15 0.05574001697823405 0.05574001697823405 0.05 0.05
As you can see, the values of the sprite’s x and y properties get floored down to the nearest 0.05 of a pixel (i.e. Math.floor(value * 20) / 20). The solution to the problem is to store the x and y coordinates used in the calculation separately (i.e. in a Point object), instead of reading them directly from the sprite.
August 18th, 2009 at 5:08 am
Cool,
and you solved it !!!
The solution to the problem is to store the x and y coordinates used in the calculation separately (i.e. in a Point object), instead of reading them directly from the sprite.
this is so wise
thanks for the post
February 3rd, 2010 at 10:27 am
Great job, thank you for sharing.