Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Гладкая анимация (http://www.flasher.ru/forum/showthread.php?t=169255)

Kicker 01.10.2011 02:46

Гладкая анимация
 
Пытаюсь создать плавное движение текста, но во время движения он временами дергается и выглядит убого.
Пробовал двумя способами (обычным и блитированием) - результат одинаковый.
Может кто подскажет как можно это исправить.

Пример:
http://stulnikov.com/example/

Код:
Код AS3:

        public class Main extends Sprite 
        {
                [Embed(source = "assets/image.png")] private var SomeImage:Class;
 
                private var item:BitmapData;
                private var itemRect:Rectangle;
                private var screen:BitmapData;
                private var rect:Rectangle;
                private var point:Point;
 
                private var image:Bitmap;
 
                public function Main():void
                {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
                }
 
                private function init(e:Event = null):void
                {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
 
                        screen = new BitmapData(800, 600, false);
                        rect = new Rectangle(0, 0, screen.width, screen.height);
                        point = new Point(-100, 100);
                        item = new SomeImage().bitmapData;
                        itemRect = new Rectangle(0, 0, item.width, item.height);
 
                        image = new SomeImage();
                        image.x = -100;
                        image.y = 100;
 
                        addChild(new Bitmap(screen));
                        //addChild(image);
 
                        addChild(new Stats());
 
                        addEventListener(Event.ENTER_FRAME, enterfFrame);
                }
 
                private function enterfFrame(e:Event):void
                {
                        animation1();
                        //animation2();
                }
 
                private function animation1():void
                {
                        screen.lock();
                        screen.fillRect(rect, 0xFFFFFF);
                        screen.copyPixels(item, itemRect, point);
                        screen.unlock();
                        point.x += 5;
                }
 
                private function animation2():void
                {
                        image.x += 5;
                }
 
        }

Исходники (FlashDevelop проект):
http://stulnikov.com/example/TestAnimation.rar

flax4Noob 01.10.2011 03:10

Тебе надо в animation1()
Получить getTimer(), потом от него отнять getTimer() предыдущего кадра. Ты получишь сколько времяни прошло между кадрами.
Дальше, зная время, и взяв скорость из настроек класса (например, 2 пикселя в секунду) ты считаешь на сколько пикселей тебе надо подвинуть текст. Двигаешь, рисуешь. Запоминаешь текущее время.

Вроде все. Должно быть равномерно плавненько.

Добавлено через 2 минуты
а, ну и еще не надо перерисовывать, если расстояние меньше одного пикселя. оО и не надо запоминать такое время.

stweet 01.10.2011 03:44

вы используете "ENTER_FRAME" что зависит от частоты обновления экрана.
что если так:
Код AS3:

package {
 
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
        import flash.events.TimerEvent;
        import flash.text.TextField;
        import flash.text.TextFieldAutoSize;
        import flash.text.TextFormat;
        import flash.utils.getTimer;
        import flash.utils.Timer;
 
        public class TestMove extends Sprite {
 
                public function TestMove() {
 
                        if (stage) ADDED_TO_STAGE();
                        else addEventListener(Event.ADDED_TO_STAGE, ADDED_TO_STAGE);
 
                        function ADDED_TO_STAGE(e:Event = null):void {
                                removeEventListener(Event.ADDED_TO_STAGE, ADDED_TO_STAGE);
                                // start point
 
                                var xPos:Number = 100;
                                var yPos:Number = 100;
 
                                var tf:TextField= new TextField();
                                        tf.text                = "Clic me!";
                                        tf.autoSize = TextFieldAutoSize.LEFT;
                                        tf.setTextFormat(new TextFormat("Arial", 28, 0x808080));
                                        tf.x = xPos;
                                        tf.y = yPos;
                                        addChild(tf);
 
                                var speed:Number = 10;
                                var delay:Number = 10;
 
                                var move:Boolean = true;
 
                                var la        :Number = getTimer();
 
                                var timer:Timer = new Timer(delay);
                                        timer.addEventListener(TimerEvent.TIMER, function (e:TimerEvent):void {
                                                tf.x += speed + (la - getTimer()) * .1;
                                                if (tf.x >= stage.stageWidth - xPos) tf.x = xPos;
                                                e.updateAfterEvent();
                                                la = getTimer();
                                        });
 
                                stage.addEventListener(MouseEvent.MOUSE_DOWN, function(e:MouseEvent):void {
                                                if (move) timer.start(); else timer.stop();
                                                move = !move;
                                        });
                        }
                }
        }
}


fljot 01.10.2011 04:05

Может просто fps поднять? Судя по http://www.greensock.com/blitmask/ copyPixels, действительно, должен быть самым гладким вариантом.

Kicker 02.10.2011 03:39

Воспользовался советами - переделал на Timer.
Код AS3:

                var timer:Timer = new Timer(1);
                timer.addEventListener(TimerEvent.TIMER, animation);
                ...
 
                private function animation(e:TimerEvent):void
                {
                        var time:Number = getTimer() - last;
                        point.x += time * .16;
                        screen.lock();
                        screen.fillRect(rect, 0xFFFFFF);
                        screen.copyPixels(item, itemRect, point);
                        screen.unlock();
                        last = getTimer();
                }

Результат:
http://stulnikov.com/example2/

По моему не особо отличается.

To:fljot
С fps экспериментировал, положительных результатов не добился.

Попробую просто сделать гифку, может красивее получится ))

in4core 02.10.2011 04:24

Цитата:

Код AS3:

stage.frameRate = 33;


..................

flax4Noob 02.10.2011 06:08

Цитата:

Сообщение от Kicker (Сообщение 1036118)
Воспользовался советами - переделал на Timer.
Код AS3:

                var timer:Timer = new Timer(1);


Плакал

Цитата:

Сообщение от Kicker (Сообщение 1036118)
Код AS3:

 
                        var time:Number = getTimer() - last;
                        [skiped]
                        last = getTimer();

Результат:[SKIPED]

Ясное дело, что результат соответствует коду. Вы не понимаете схемы работы таймера и, самое главное, схемы анимации. Вам жизненно необходимо сохранять getTimer() в переменную, чтобы "getTimer() - last" учитывало время прорисовки. В вашем варианте оно не учитывается. поэтому, естественно, получаются рывки. И, естественно, вы разочарованы. Попробуйте так:
Код AS3:

var frameTime:uint = getTimer();
var time:Number = frameTime - last;
last = frameTime;
 
и дальше свое колдовство с битмапами.

И таймер ставится в "секунда/1000" => бессмысленно ставить значения ниже 40. Хотя для анимации 25 фпс достаточно 100 поставить.

Kicker 02.10.2011 12:57

Действительно туплю.
Стало лучше, но все равно двигается рывками, хоть и равномерными ))

stweet 02.10.2011 16:21

Цитата:

Сообщение от Kicker (Сообщение 1036144)
Действительно туплю.
Стало лучше, но все равно двигается рывками, хоть и равномерными ))

Предлагаю ещё раз рассмотреть тот код который дал я и добавить к своим задачам использование методов:
Timer(); Управляем анимацией.
getTimer(); Расчёт времени на перерисовку избегая ошибок в движении.
updateAfterEvent(); Перерисовываем анимацию программно(обновляем экран) т.е. только после того как методы выше выполнили свои задачи.

Добавлено через 5 минут
Цитата:

point.x += time * .16;
у вас тут "time" постоянно разный, естественно будит рывками!
избегая вычитайте "time" из целого числа тогда получите равный интервал после каждой перерисовки экрана.
Цитата:

point.x += (number - time) * .16;

-De- 02.10.2011 17:12

Цитата:

Сообщение от stweet (Сообщение 1036168)
у вас тут "time" постоянно разный, естественно будит рывками!
избегая вычитайте "time" из целого числа тогда получите равный интервал после каждой перерисовки экрана.

Так время между перерисовками реально разное. Плюс для анимаций ENTER_FRAME надёжнее таймера, т.к. после него гарантированно идёт перерисовка.


Часовой пояс GMT +4, время: 08:46.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.