views:

76

answers:

2

I have the following bit of code:

protected function onEnterFrame(e:Event):void 
{
    var diff:Number;

    // position map/tree
    if (x != _targetX) {
        diff = _targetX - x; // get the difference
        x += diff * 0.2; // tween x position
        diff = diff < 0 ? -diff : diff; // get absolute value
        if (diff < 0.05) {
            x = _targetX;
        }
    }
}

I set _targetX to only one of two values in my app: 0 or -1360. When I set it to 0 the tween executes as you would expect. When I set it to -1360 a strange thing happens... the tween executes as you would expect until the very last bit. x reaches -1359.8 and diff reaches 0.20000000000004547 and it's at this point that it just stalls out. x no longer approaches _targetX and these values just hold. They won't budge. As a result the if (diff < 0.05) conditional never evaluates to true and the tween logic continues to execute indefinitely.

I'm guessing it has something to do with floating point precision, but I'm unsure of a solution. Any ideas?

+2  A: 

As you say, it could be a problem to do with floating point precision. I just put your code into an empty Flash project, using only variables instead of any actual object's positional properties, and your code worked fine - diff reached a number less than 0.05 and the code stopped executing.

I then tried with an object on the stage, and used it's x value, and ran into exactly the problem you described. One easy solution seems to be to use an object of type Number to do the calculations, then at the end of the statement set your object's x value equal to the variable. I've pasted the code I used below, where 'box' is the object I put on the stage:

addEventListener(Event.ENTER_FRAME, onEnterFrame);

var someX:Number = 0;
var _targetX:Number = -1360;

function onEnterFrame(e:Event):void 
{
    var diff:Number;

    // position map/tree
    if (someX != _targetX) 
    {
        diff = _targetX - someX; // get the difference

        someX += diff * 0.2; // tween x position
        trace("diff= ", diff, " x= ", someX);

        diff = diff < 0 ? -diff : diff; // get absolute value
        //You could equally use diff = abs(diff); here

        if (diff < 0.05) 
        {
             trace("target reached; x set to targetX");
             someX = _targetX;
        }
        box.x = someX;
    }
}

I hope that helps.

debu
Thanks debu! Your solution indeed works. Now I want to know *why* :)
heavilyinvolved
No problem, glad it helped! Looks like another guy posted a reason why too, so all cleared up :)
debu
A: 

I had a similar issue. Maybe these can help you understand the 'why' http://www.lordofduct.com/blog/?p=90 http://www.lordofduct.com/blog/?p=101

ThunderChunky_SF
Awesome, thanks!
heavilyinvolved
I did a quick test and came across the following. If you add a display object to the stage, add an enter frame listener and then try to increment the display objects x pos by anything less than or equal to 0.05 this issue occurs. But if you increment it by 0.051, all is well. wtf?!?!
heavilyinvolved
I can't begin to explain how it all works. I'm still learning it myself. Why don't you just use a simple tweening engine like TweenLite? TweenLite.to(myMc, 1, { x: -1360 }); Jack Doyle and Grant Skinner are two of the smartest developers out there and they've already solved these problems for us. It's definitely good to understand the underlying issue but to achieve your goal there's no sense in reinventing the wheel.
ThunderChunky_SF
@ThunderChunky_SF yes I'm quite familiar with most of the tween engines out there. I have used Tweener exclusively for the last couple of years. Perhaps I'm stubborn, or a masochist, or some combination of the two, but I like writing my own tweens :) Thanks for chiming in...
heavilyinvolved