вторник, 10 ноября 2009 г.

Tween останавливается?

Да. В Actionscript3 порой удобней "запустить" какой-нибудь Tween и забыть о нем, чем вешать обработчик на ENTER_FRAME и вручную менять какой-то scaleX, например. Но. Tween иногда непредсказуемо останавлиается! Как этого гарантированно избежать?
Tween нельзя запускать так:


new Tween(myMovieClip, "alpha", 0, 1, null, 1, true);



Потому что при очередном проходе GC (Garbage Collector — сборщик мусора) ваш Tween улетит в мусорник. Так происходит с любым объектом, если:

  1. нет ссылок на этот объект

  2. не прописано никаких обработчиков событий

  3. он не является дочерним ни для одного DisplayObjectContainer (если он сам является экзеспляром DisplayObject)


Решение для случая, когда нужно сделать какую-то простую анимацию, подразумевает наличие глобальной переменной типа Tween:

myGlobalTweenKeeper = new Tween(myMovieClip, "alpha", 0, 1, null, 1, true);


А в случае, когда нужно синхронно сделать анимацию нескольких параметров одного объекта, я пользуюсь глобальным массивом:

myGlobalTweenKeeperArray = new Array();
myGlobalTweenKeeperArray.push(new Tween(myMovieClip, "alpha", 0, 1, null, 1, true));
myGlobalTweenKeeperArray.push(new Tween(myMovieClip, "scaleX", 2, 1, null, 1, true));
myGlobalTweenKeeperArray.push(new Tween(myMovieClip, "scaleY", 2, 1, null, 1, true));


В обоих случаях также рекомендую прописать обработчик события завершения анимации:

// для первого примера
myGlobalTweenerKeeper.addEventListener(TweenEvent.MOTION_FINISH, onFinish);

// для второго примера
myGlobalTweenerKeeperArray[0].addEventListener(TweenEvent.MOTION_FINISH, onFinish);


Во втором случае я приписал обработчик лишь для одной анимации, потому что все анимации имеют одинаковый хронометраж. В случае, когда синхронные анимации заканчиваются не в один момент, следует выбрать самую долгую.
В самом же обработчике onFinish() нужно отписаться от события и обнулить наших "хранителей", чтобы GC мог их удалить из памяти при очередном обходе:

private function onFinish(e:TweenEvent):void
{
e.target.removeEventListener(TweenEvent.MOTION_FINISH, onFinish);

// для первого примера
myGlobalTweenKeeper = null;

// для второго примера я делаю так
myGlobalTweenKeeperArray = new Array();
}


И все анимации проигрываются до конца.

0 коммент.:

Отправить комментарий