ActionScript 3 проблема встряхивания анимации - PullRequest
1 голос
/ 22 августа 2011

, пожалуйста, помогите мне, мой клиент убивает меня!

вот ссылка: http://aradon.co.il/test/circles.html

теперь вы видите, как трясется круг !!!мой клиент не одобрит это так.

что может быть причиной этого?

он построен так

один вызов класса, который имеет событие EnterFrame

и 6 кругов, которые имеют каждый круг:

    private var _aPosition:Number = 0;

    public function get aPosition():Number
    {
        return _aPosition;
    }

    public function get aRadians():Number
    {
        return  180 / Math.PI * _aPosition;
    }

    public function set aPosition(value:Number):void
    {
        _aPosition = value % 360;

        if(parentPath)
        {
            x = Math.cos(aRadians) * (parentPath.width / 2);
            y = Math.sin(aRadians) * (parentPath.height / 2);
        }
    }

так, как я могу вращать круг вокруг пути.

теперь у класса пути есть код на enterframe:

    private function this_enterframe(e:Event=null):void
    {
        for(var i:int = 0; i < numCircles; i++)
        {
            getCircleAt(i).aPosition += direction == RIGHT ? -speed : speed;


        }
    }

изображения на кругах - это динамика, а также текст, но он трясся, прежде чем я их добавил.

частота кадров составляет 30, я пробовал также 25 20 40, и это уже трясло ??

, пожалуйста, дайте мне подсказку.

ОБНОВЛЕНИЕ: я добавил в конструктор класса круга:

      z = 1

как @Sean Fujiwara советовал, есть большое улучшение

вот ссылка: http://aradon.co.il/test2/circle.htm

но сталь клиент сказал мне, что это сталь не хорошо.

Ответы [ 7 ]

1 голос
/ 22 августа 2011

cacheAsBitmap может немного помочь, если вы установите его в классе Circle. Это не поможет, и на самом деле может повредить, если вы установите его в основном классе. Вы получите лучший импульс от cacheAsBitmap при установке его на объект DisplayObject, чьи дочерние объекты не изменяются, поэтому он может кэшировать его один раз, а затем только транслировать этот объект на сцене. Если дочерние элементы движутся (как в случае с parent), то он должен перерисовывать и перерисовывать этот элемент каждый кадр, и вы не получаете никакого повышения производительности. cacheAsBitmap действительно лучше всего работает с элементами, которые имеют сложную векторную графику, которую трудно перерисовать, но редко меняют.

Я не думаю, что округление ваших значений x и y поможет, у меня никогда не было особых проблем с установкой дробного x, y. Для векторной графики это обычно довольно хорошо работает при размещении субпикселей, а для растровых изображений это обычно работает так, как я ожидал.

Я думаю, вы можете использовать анимацию, не зависящую от частоты кадров. То, как ваш код структурирован сейчас, каждый кадр показывает, что вы перемещаетесь на определенное количество градусов. Это означает, что если частота кадров заикается по какой-либо причине, вы все равно будете перемещать то же количество пикселей.

Вот направление, в котором я бы пошел:

Сначала ваш обработчик события enter frame получает несколько обновлений. getTimer() возвращает текущее количество миллисекунд с момента запуска swf. Таким образом, запомнив lastTime, который мы отрендерили, и вычтя currentTime, мы сможем точно определить, сколько миллисекунд прошло с момента последнего кадра. Затем мы можем обновить наш круг, используя это время, а не произвольную скорость / расстояние.

private var lastTime:int;

private function this_enterframe(e:Event = null):void {
    var currentTime:int = getTimer();
    var elapsedTime:int = currentTime - lastTime;
    lastTime = currentTime;

    for(var i:int = 0; i<numCircles; i++)
    {
        getCircleAt(i).updatePosition(elapsedTime, direction)
    }
}

Тогда в вашем классе Круга мы сможем вычислить, как далеко он должен был продвинуться за определенный промежуток времени (в этом случае я ввел его скорость как число радиан в секунду, в которое он должен двигаться).

Что-то вроде:

public class Circle extends MovieClip {

    // Set the default speed to 10 degrees per second
    public const DEFAULT_SPEED:Number = 10 * Math.PI / 180;

    private var _radiansPerSecond = Circle.DEFAULT_SPEED;
    private var _rotationPosition:Number = 0;

    public function updatePosition(elapsedTime:int, direction:*):void { 
        var chng:Number = _radiansPerSecond * (elapsedTime / 1000) * (direction == RIGHT ? -1 : 1);
        _rotationPosition += chng;
        this.x = Math.cos(_rotationPosition) * (parentPath.width / 2);
        this.y = Math.sin(_rotationPosition) * (parentPath.height / 2); 
    }
}

Между использованием радианов вместо градусов и динамическим вычислением того, как далеко должен двигаться круг, основываясь на времени, прошедшем с момента последнего рендеринга, я думаю, вы должны быть в состоянии уменьшить дрожание, которое вы видите.

0 голосов
/ 22 августа 2011

Нарисуйте круги в растровые изображения, затем примените сглаживание.

0 голосов
/ 22 августа 2011

Я получаю это, если я пытаюсь оживить текст. Итак, чтобы исправить это, я просто разбиваю текст на части (щелкните текст и дважды нажмите CTRL + B).

Ваши образы этих маленьких человечков разбиты на части? Попробуйте выбрать один и сломать его (нажав CTRL + B). Кроме того, этот текст внутри кругов, если это статический текст, просто попробуйте разбить его, чтобы увидеть, устраняет ли это дрожание.

0 голосов
/ 22 августа 2011

Поскольку это звучит так, как будто вы спешите, попробуйте поместить это в конструктор Path:

z = 1;

Вы можете увидеть, что теперь он выполняет субпиксельный рендеринг, если вы установите speed = 0.00001.

Кроме того, я вижу, что вы устанавливаете cacheAsBitmap = true в объекте пути.Это только плохо для производительности.

0 голосов
/ 22 августа 2011

e.updateAfterEvent();.

Но чтобы использовать это, вам нужно использовать Timer класс.

Это повысит плавность, пока все происходит.

0 голосов
/ 22 августа 2011

Всегда проверяйте, чтобы ваши позиции x и y были целыми числами, полупикселя не существует, но Flash все равно пытается это сделать.

Это должно быть просто округление значений x и y:

x = Math.round( Math.cos(aRadians) * (parentPath.width / 2) );
y = Math.round( Math.sin(aRadians) * (parentPath.height / 2) );
0 голосов
/ 22 августа 2011

попробуйте установить cacheAsBitmap в true для каждого движущегося объекта DisplayObject. Это может сгладить вашу анимацию.

Если ваши круги являются растровыми, вы можете попробовать включить сглаживание.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...