flash as3 - использование tweenmax и класса графики flash вместе - PullRequest
1 голос
/ 23 ноября 2011

Я пытаюсь найти хороший способ использовать TweenMax и класс рисования во флэш-памяти, но он всегда тормозит и вылетает во флэш-плеер, и я не могу понять, что происходит не так.На самом деле все, что я хочу сделать, это убедиться, что, когда два (или более) круга, соединенных линией, движутся, линия между ними следует.Это мой код:

import com.greensock.TweenMax;

var sw = stage.stageWidth;
var sh = stage.stageHeight;
var cr = 3; //circle radius
var moveRange = 20;
var circleColor = 0xcccccc;
var numCircles = 2;
var circleArray = [];
var lineCanvas:Sprite = new Sprite();
addChild(lineCanvas);
var lineColor = 0xe9e9e9;
var lineWeight = 1;

function init(){
    drawCircle();
}

function drawCircle(){
    for (var i = 0; i<numCircles; i++){
        var xPos = randomRange(cr, sw-cr);
        var yPos = randomRange(cr, sh-cr);
        var newCircle:Shape = new Shape();
        newCircle.graphics.beginFill(circleColor);
        newCircle.graphics.drawCircle(0,0,cr);
        newCircle.x = xPos;
        newCircle.y = yPos;
        newCircle.graphics.endFill();
        circleArray.push(newCircle);
        addChild(newCircle);
    }
    drawLine();
}

function drawLine(){
    for (var i = 0; i<numCircles-1; i++){
        lineCanvas.graphics.clear();
        lineCanvas.graphics.lineStyle(lineWeight,lineColor);
        lineCanvas.graphics.moveTo(circleArray[i].x,circleArray[i].y);
        lineCanvas.graphics.lineTo(circleArray[i+1].x,circleArray[i+1].y);
    }
    moveCircle();
}

function moveCircle(){
    for (var i = 0; i<numCircles; i++){
        var curX = circleArray[i].x;
        var curY = circleArray[i].y;
        var moveX = randomRange(curX-moveRange,curX+moveRange);
        var moveY = randomRange(curY-moveRange,curY+moveRange);
        //TweenMax.to(circleArray[i],.5, { x: moveX, y: moveY, onUpdate:drawLine });
    }
}

function randomRange(minNum:Number, maxNum:Number):Number {  
    return (Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum);  
}

init();

Есть ли лучший способ сделать это?Разве я не должен использовать библиотеку анимации?

Ответы [ 2 ]

3 голосов
/ 23 ноября 2011

Предполагая, что вы раскомментируете эту строку TweenMax, функция drawLine() вызывает moveCircle() ..., которая добавляет анимацию для каждого круга, которая снова вызовет drawLine() - и все повторяется. Я предполагаю, что это добавляет тонны * слушателей и подростков, что приводит к сбою. Вы должны добавить проверку, которая предотвращает добавление других анимаций, в то время как анимация для этого круга еще выполняется.

Также, lineCanvas.graphics.clear(); должен быть перемещен перед циклом, иначе он очистит линии, нарисованные для других кругов, если они есть.

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


Изменить:
* Мне нравятся цифры. Предполагая, что частота кадров составляет 24 кадра в секунду, вы действительно получаете очень много подростков. Растет экспоненциально. 1 анимация при инициализации, 2 анимации в первом кадре, 4 во втором и т. Д. Когда первая анимация закончится (если бы она делала это до аварии), у вас получилось бы симпатичное число бегущих 2 ^ 24-1. 16777215 подростков. Для каждого круга.

А если серьезно, чтобы исправить это, вы можете использовать TweenMax.isTweening(circleArray[i]), чтобы проверить, запущена ли уже анимация движения. Я думаю drawLine не должен звонить moveCircle. Функция moveCircle теперь должна вызываться только один раз, чтобы запустить анимацию движения - или, если вы хотите, чтобы она повторялась, каждый раз, когда анимация завершается (onComplete).

1 голос
/ 24 ноября 2011

, поскольку mheavers спросил меня, я собрал небольшой пример использования слушателя ENTER_FRAME для анимации кругов вручную.

У меня есть два класса:

package
{
    import flash.filters.BlurFilter;
    import flash.events.Event;
    import flash.display.Sprite;

    [SWF(backgroundColor="#000000", frameRate="60", width="960", height="600")]
    public class Main extends Sprite
    {
        private var numCircles:int = 2;
        private var circles:Vector.<Circle>;
        private var lineCanvas:Sprite;
        private var lineColor:uint = 0xe9e9e9;
        private var lineWeight:int = 1;
        private var blur:BlurFilter;

        public function Main()
        {
            init();
        }

        private function init():void
        {
            circles = new Vector.<Circle>();
            blur = new BlurFilter();

            lineCanvas = new Sprite();
            addChild(lineCanvas);

            drawCircle();

            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }

        private function drawCircle():void
        {
            for (var i:int = 0; i < numCircles; i++)
            {
                var newCircle:Circle = new Circle();
                circles.push(newCircle);
                addChild(newCircle);
            }
            drawLine();
        }

        private function drawLine():void
        {
            var circle:Circle;
            var nextCircle:Circle;
            for (var i:int = 0; i < circles.length-1; i++)
            {
                circle = circles[i];
                nextCircle = circles[i+1];

                //lineCanvas.graphics.clear();
                lineCanvas.graphics.lineStyle(lineWeight, lineColor);
                lineCanvas.graphics.moveTo(circle.x, circle.y);
                lineCanvas.graphics.lineTo(nextCircle.x, nextCircle.y);
            }
        }

        private function onEnterFrame(event:Event):void
        {
            // update circles
            var circle:Circle;
            for (var i:int = 0, len:int = circles.length; i < len; i++)
            {
                circle = circles[i];
                circle.move();
            }

            drawLine();
        }
    }
}

и еще один для круга:

package
{
    import flash.events.Event;
    import flash.display.Shape;

    public class Circle extends Shape
    {
        public var targetx:Number;
        public var targety:Number;

        private var circleColor:uint = 0xcccccc;
        private var cr:int = 3;
        private var moveRange:int = 150;

        public function Circle()
        {
            graphics.beginFill(circleColor);
            graphics.drawCircle(0, 0, cr);
            graphics.endFill();

            addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
        }

        public function move():void
        {
            var absx:Number = Math.abs(targetx-x);
            var absy:Number = Math.abs(targety-y);

            if (absx < 1 && absy < 1)
            {
                targetx = randomRange(x - moveRange, x + moveRange);
                targety = randomRange(y - moveRange, y + moveRange);

                if (targetx >= stage.stageWidth)
                {
                    targetx = stage.stageWidth - moveRange;
                }
                else if (targetx <= 0)
                {
                    targetx = moveRange;
                }

                if (targety >= stage.stageHeight)
                {
                    targety = stage.stageHeight - moveRange;
                }
                else if (targety <= 0)
                {
                    targety = moveRange;
                }
            }
            else
            {
                x += (targetx - x) * 0.125;
                y += (targety - y) * 0.125;
            }
        }


        private function onAddedToStage(event:Event):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);

            // position circle on stage
            x = targetx = randomRange(cr, stage.stageWidth - cr);
            y = targety = randomRange(cr, stage.stageHeight - cr);
        }

        private function randomRange(minNum:Number, maxNum:Number):Number
        {
            return (Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum);
        }
    }
}

выглядит так:

example

...