【问题标题】:flash as3 - using tweenmax and flash's graphics class togetherflash as3 - 一起使用 tweenmax 和 flash 的图形类
【发布时间】:2011-11-23 17:38:42
【问题描述】:

我正在尝试找到一种同时使用 TweenMax 和 flash 的绘图类的好方法,但它总是卡住并导致 flash 播放器崩溃,我真的不知道出了什么问题。实际上,我要做的就是确保当两个(或更多)由一条线连接的圆圈移动时,它们之间的线会跟随。这是我的代码:

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();

有没有更好的方法来做到这一点?我不应该使用补间库吗?

【问题讨论】:

  • 对于某些事情,使用 ENTER_FRAME 侦听器并手动移动对象比使用 Tween-Engine/Library 更容易......只是说;)
  • 你有我如何修改代码来做到这一点的例子吗?
  • 我发布了一个 ENTER_FRAME 的例子

标签: flash actionscript-3 graphics drawing tween


【解决方案1】:

假设您取消注释 TweenMax 行,函数 drawLine() 调用 moveCircle()... 为每个圆圈添加一个补间,这将再次调用 drawLine() - 一切都在重复。我想这会增加大量的听众和补间,导致崩溃。您应该添加一个检查,以防止添加其他补间,而该圆圈仍在运行补间。

另外,lineCanvas.graphics.clear(); 应该移到循环之前,否则它会清除为其他圆圈绘制的线条,如果有的话。

补间库很好,如果可以的话,你应该使用一个。即使是简单的补间任务,它们也很有帮助。


编辑:
* 我喜欢数字。假设每秒 24 帧的帧速率,你真的会得到相当多的补间。呈指数增长。初始化时有 1 个补间,第一帧有 2 个补间,第二帧有 4 个,以此类推。当第一个补间完成时(如果它在崩溃之前这样做),您将运行大量 2^24-1 个补间。 16777215 补间。对于每个圈子。

但是现在说真的,要解决这个问题,您可以使用TweenMax.isTweening(circleArray[i]) 检查是否已经有一个补间正在运行。我认为drawLine 不应该打电话给moveCircle。函数 moveCircle 现在应该只被调用一次,以启动补间 - 或者如果您希望它循环,则每次补间完成时 (onComplete)。

【讨论】:

  • 感谢您指出 drawLine 调用 moveCircle 的问题 - 我没有意识到正在创建的循环..
【解决方案2】:

因为 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);
        }
    }
}

看起来像这样:

【讨论】:

  • 谢谢-这看起来很棒-我尝试使用您的课程,但引用 的行出现错误-我以前从未见过这种表示法。我确保添加 import Circle;但它似乎没有帮助。
  • Vector.&lt;Circle&gt; 表示一种数组,但它只能包含圆形对象。因此,当您从“数组”/向量中检索对象时,您可以确定它们是 Circles 并且您不必强制转换它们。它比通常的 Array 更快,它是 flashplayer 10 的一个功能。如果您仍在使用 fp9,您可以将其更改为 Array。
猜你喜欢
  • 1970-01-01
  • 2010-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多