Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
337 views
in Technique[技术] by (71.8m points)

flash - Moving symbol around drawing objects

I have imported a lot of paths from an Adobe Illustrator document right into a flash file. The paths exists as Drawing Objects inside the scene. Using pure actionscript, how can I move a symbol following each of the lines, without using predefined Motion Guides.

EDIT: I've attached the Flash file, full of drawing objects.

http://rapidshare.com/files/406497264/pather.fla.html

The question is: Are these drawing objects accessible through AS3 or I should convert them to symbols / whatever format necessary. And please give some AS examples.

Thanks!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Nice question +1

I've seen the fla at work, don't have cs5 home, but I understand what you're trying to achieve.

My approaches were these:

  1. Motion Paths:

Since Flash CS4 you can copy a path, and paste it onto a Motion Tween. This will work similar to the Classic Tween's Motion Guide feature. There are quite a few problems with this:

  • You might need to manually do the cut/paste
  • Not all paths can be pasted onto a motion
  • You can use the AnimationFactory class and add a target, but the problem is, while the target is animating, you have no actionscript control over it. You can set a timer for the duration of the AnimationFactory's motion, but it gets to cumbersome.

Obviously this is a no-no.

  1. Using JSFL to traverse the paths inside the IDE:

    I stumbled upon this very handy jsfl script by ericlin which traverses all shapes selected on stage. If you select your paths and run the script(you can just double click the jsfl file), you will get the parsed coordinates.

I did a simple test using TweenLite:

import com.greensock.*;
import com.greensock.easing.*;
import com.greensock.plugins.*;

TweenPlugin.activate([BezierPlugin]);

graphics.lineStyle(0.05);
var index:int = 0;
var ball:Sprite = new Sprite();
ball.graphics.beginFill(0x009900,.75);ball.graphics.drawCircle(-2,-2,4);ball.graphics.endFill();
addChild(ball);

drawLines();

function drawLines():void{
    var t:Number = .01;
    var timeline:TimelineLite = new TimelineLite();
    var i:int = index;
    for(index; index <= ptArray.length; index += 12){
        timeline.append( new TweenLite(ball, t, {x:ptArray[i],y:ptArray[i+1]}) );
        timeline.append( new TweenLite(ball, t, {bezier:[{x:ptArray[i+2], y:ptArray[i+3]}, {x:ptArray[i+4], y:ptArray[i+5]}]}) );
        this.graphics.moveTo(ptArray[i], ptArray[i+1]);
        this.graphics.curveTo(ptArray[i+2], ptArray[i+3], ptArray[i+4], ptArray[i+5]);
        i += 6;
        timeline.append( new TweenLite(ball, t, {x:ptArray[i],y:ptArray[i+1]}) );
        timeline.append( new TweenLite(ball, t, {bezier:[{x:ptArray[i+2], y:ptArray[i+3]}, {x:ptArray[i+4], y:ptArray[i+5]}]}) );
        this.graphics.moveTo(ptArray[i], ptArray[i+1]);
        this.graphics.curveTo(ptArray[i+2], ptArray[i+3], ptArray[i+4], ptArray[i+5]);
    }
}

*Note:*The ptArray isn't shown here because it would waste too much space. The result isn't that great though. You can have a look at the fla to see what I mean. The jsfl script could be altered, but I saw you emphasised actionscript usage, so this is a no no as well.

  1. Using AS3SWF to decompile the swf at runtime and access the shapes:

Claus Wahlers developed an amazing as3 library called as3swf which allows flash/flex developers to decompile swfs at runtime. Here is an awesome article explaining the ins and outs of shapes inside swfs. There are quite a few exporters already written.

I just duplicated the AS3ShapeExporter and changed the as3 draw commands to TweenLite code. Basically I replaced moveTo with a fast tween to position, lineTo, to a regular tween and curveTo with a bezier tween. Tween Lite's BezierPlugin luckily used quadratic bezier, just like curveTo does.

Here is the code you will need to paste inside the fla that holds the shapes:

import com.codeazur.as3swf.*;
import com.codeazur.as3swf.tags.*;
import com.codeazur.as3swf.exporters.*;

this.loaderInfo.addEventListener(Event.COMPLETE, completeHandler);

function completeHandler(e:Event):void {
    var swf:SWF = new SWF(this.loaderInfo.bytes);//new SWF(URLLoader(e.target).data as ByteArray);
    var doc:AS3ShapeTweenLiteExporter = new AS3ShapeTweenLiteExporter(swf,"ball",.01);
    // Loop over all tags
    for (var i:uint = 0; i < swf.tags.length; i++) {
        var tag:ITag = swf.tags[i];
        // Check if tag is a DefineShape
        if (tag is TagDefineShape) {
          // Export shape tween
          TagDefineShape(tag).export(doc);

        }
    }
    trace(doc.actionScript);
}

Basically I load the swf, once it's ready, I pass it's bytes to as3swf and use the AS3ShapeTweenLiteExporter to parse shape tags and spit out actionscript. The 3 paramaters I pass to the constructor are : the swf instance, a name for the tween target and a time for each tween.

Here's how my hacked together class looks like:

package com.codeazur.as3swf.exporters
{
    import com.codeazur.as3swf.SWF;
    import com.codeazur.utils.StringUtils;

    import flash.display.CapsStyle;
    import flash.display.InterpolationMethod;
    import flash.display.JointStyle;
    import flash.display.LineScaleMode;
    import flash.display.SpreadMethod;
    import flash.geom.Matrix;
    import com.codeazur.as3swf.exporters.core.DefaultShapeExporter;

    public class AS3ShapeTweenLiteExporter extends DefaultShapeExporter
    {
        protected var _actionScript:String;
        protected var _target:String;
        protected var _time:Number;

        public function AS3ShapeTweenLiteExporter(swf:SWF,target:String,time:Number) {
            super(swf);
            _target = target;
            _time = time;
        }

        public function get actionScript():String { return _actionScript; }

        override public function beginShape():void {
            _actionScript = "import com.greensock.*;
import com.greensock.plugins.*;

TweenPlugin.activate([BezierPlugin]);

var shapeTimeline:TimelineLite = new TimelineLite()
";
        }

        override public function beginFills():void {
            //_actionScript += "// Fills:
graphics.lineStyle();
";
        }

        override public function beginLines():void {
            //_actionScript += "// Lines:
";
        }

        override public function beginFill(color:uint, alpha:Number = 1.0):void {
            if (alpha != 1.0) {
                _actionScript += StringUtils.printf("graphics.beginFill(0x%06x, %f);
", color, alpha);
            } else {
                _actionScript += StringUtils.printf("graphics.beginFill(0x%06x);
", color);
            }
        }

        override public function beginGradientFill(type:String, colors:Array, alphas:Array, ratios:Array, matrix:Matrix = null, spreadMethod:String = SpreadMethod.PAD, interpolationMethod:String = InterpolationMethod.RGB, focalPointRatio:Number = 0):void {
            var asMatrix:String = "null";
            if (matrix != null) {
                asMatrix = "new Matrix(" +
                    matrix.a + "," +
                    matrix.b + "," +
                    matrix.c + "," +
                    matrix.d + "," +
                    matrix.tx + "," +
                    matrix.ty + ")";
            }
            var asColors:String = "";
            for (var i:uint = 0; i < colors.length; i++) {
                asColors += StringUtils.printf("0x%06x", colors[i]);
                if (i < colors.length - 1) { asColors += ","; }
            }
            if (focalPointRatio != 0.0) {
                _actionScript += StringUtils.printf("graphics.beginGradientFill('%s', [%s], [%s], [%s], %s, '%s', '%s', %s);
",
                    type,
                    asColors,
                    alphas.join(","),
                    ratios.join(","),
                    asMatrix,
                    spreadMethod,
                    interpolationMethod,
                    focalPointRatio.toString());
            } else if (interpolationMethod != InterpolationMethod.RGB) {
                _actionScript += StringUtils.printf("graphics.beginGradientFill('%s', [%s], [%s], [%s], %s, '%s', '%s'
);",
                    type,
                    asColors,
                    alphas.join(","),
                    ratios.join(","),
                    asMatrix,
                    spreadMethod,
                    interpolationMethod);
            } else if (spreadMethod != SpreadMethod.PAD) {
                _actionScript += StringUtils.printf("graphics.beginGradientFill('%s', [%s], [%s], [%s], %s, '%s');
",
                    type,
                    asColors,
                    alphas.join(","),
                    ratios.join(","),
                    asMatrix,
                    spreadMethod);
            } else if (matrix != null) {
                _actionScript += StringUtils.printf("graphics.beginGradientFill('%s', [%s], [%s], [%s], %s);
",
                    type,
                    asColors,
                    alphas.join(","),
                    ratios.join(","),
                    asMatrix);
            } else {
                _actionScript += StringUtils.printf("graphics.beginGradientFill('%s', [%s], [%s], [%s]);
",
                    type,
                    asColors,
                    alphas.join(","),
                    ratios.join(","));
            }
        }

        override public function beginBitmapFill(bitmapId:uint, matrix:Matrix = null, repeat:Boolean = true, smooth:Boolean = false):void {
            var asMatrix:String = "null";
            if (matrix != null) {
                asMatrix = "new Matrix(" +
                    matrix.a + "," +
                    matrix.b + "," +
                    matrix.c + "," +
                    matrix.d + "," +
                    matrix.tx + "," +
                    matrix.ty + ")";
            }
            if (smooth) {
                _actionScript += StringUtils.printf("// graphics.beginBitmapFill(%d, %s, %s, %s);
", bitmapId, asMatrix, repeat, smooth);
            } else if (!repeat) {
                _actionScript += StringUtils.printf("// graphics.beginBitmapFill(%d, %s, %s, %s);
", bitmapId, asMatrix, repeat);
            } else {
                _actionScript += StringUtils.printf("// graphics.beginBitmapFill(%d, %s, %s, %s);
", bitmapId, asMatrix);
            }
        }

        override public function endFill():void {
            _actionScript += "graphics.endFill();
";
        }

        override public function lineStyle(thickness:Number = NaN, color:uint = 0, alpha:Number = 1.0, pixelHinting:Boolean = false, scaleMode:String = LineScaleMode.NORMAL, startCaps:String = null, endCaps:String = null, joints:String = null, miterLimit:Number = 3):void {
            /*
            if (miterLimit != 3) {
                _actionScript += StringUtils.printf("graphics.lineStyle(%f, 0x%06x, %f, %s, %s, %s, %s, %f);
",
                    thickness, color, alpha, pixelHinting.toString(),
                    (scaleMode == null ? "null" : "'" + scaleMode + "'"),
                    (startCaps == null ? "null" : "'" + startCaps + "'"),
                    (joints == null ? "null" : "'" + joints + "'"),
                    miterLimit);
    

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...