Bob
Bob

Reputation: 8714

Multiple shapes created dynamically with ActionScript 3

I am trying to create animation in AS dynamically. I want to create multiple shapes which will animate one by one. So, first, one shape is created and animated from dot1. After that second shape should be made and animate to dot2. Number array hold positions of the dots. I use drawLine function to draw line. Before that I set 10 dots. In string fullDate I hold list of dots. Result of this code is only the first animation. I think that code does not generate well new shape, so animation finishes after first animation. Has anyone idea how to fix this issue? Thanks in advance!

  import flash.display.Shape;

var startPoint:Point = new Point();
var endPoint:Point = new Point();

var prog:Number = 0;
var bonus:Number = 1;
var frames:int = 150;

var numbers:Array = new Array();

numbers[0] = new Array();
numbers[0][0] = 460;
numbers[0][1] = 100;

numbers[1] = new Array();
numbers[1][0] = 10;
numbers[1][1] = 20;

numbers[2] = new Array();
numbers[2][0] = 10;
numbers[2][1] = 100;

numbers[3] = new Array();
numbers[3][0] = 10;
numbers[3][1] = 180;

numbers[4] = new Array();
numbers[4][0] = 160;
numbers[4][1] = 20;

numbers[5] = new Array();
numbers[5][0] = 160;
numbers[5][1] = 100;

numbers[6] = new Array();
numbers[6][0] = 160;
numbers[6][1] = 180;

numbers[7] = new Array();
numbers[7][0] = 310;
numbers[7][1] = 20;

numbers[8] = new Array();
numbers[8][0] = 310;
numbers[8][1] = 100;

numbers[9] = new Array();
numbers[9][0] = 310;
numbers[9][1] = 180;

var fullDate:String = "271524";

var i:Number;
var pom:Number;
var shapes:Vector.<Shape> = new Vector.<Shape>();
for (i=0; i < fullDate.length; i++){

    pom = int(fullDate.charAt(i));
    shapes[i] = new Shape();
    addChild(shapes[i]);

    trace(numbers[pom+1][0]);
    drawLine(numbers[pom][0], numbers[pom][1], numbers[pom+1][0], numbers[pom+1][1], 120);
}

function drawLine(startX:Number, startY:Number, endX:Number, endY:Number, time:Number = 120):void {
    startPoint.x = startX;
    startPoint.y = startY;
    endPoint.x = endX;
    endPoint.y = endY;

    frames = time;
    prog = 0;
    this.addEventListener(Event.ENTER_FRAME, tick);
}

function drawLineTick(progress:Number):void{
    for each(var shape:Shape in shapes)
    {
        shape.graphics.clear();
        shape.graphics.lineStyle(14,0x2dfdfd);

        shape.graphics.moveTo(startPoint.x,startPoint.y);
        shape.graphics.lineTo(startPoint.x + ((endPoint.x - startPoint.x) * progress), startPoint.y + ((endPoint.y - startPoint.y) * progress));

    }

}

function tick(e:Event):void {
    if(prog >= frames){
        this.removeEventListener(Event.ENTER_FRAME, tick);
    }

    drawLineTick(prog / frames);    
    prog += bonus;
} 

Upvotes: 1

Views: 1163

Answers (1)

net.uk.sweet
net.uk.sweet

Reputation: 12431

Because of the asynchronous nature of ActionScript, the drawLine method is invoked on each of your shapes before the first tick is executed. The drawTickLine method then draws the (same) line with the points related to the last part of the date in each of the shapes you created.

The following might not be perfect because it's not 100% clear from your question what the results should be, but hopefully it should give you a push in the right direction. I've tried to include comments to explain my thinking.

import flash.display.Shape;
import flash.geom.Point;
import flash.events.Event;

var startPoint:Point = new Point();
var endPoint:Point = new Point();

var count:int = 0;
var prog:Number = 0;
var bonus:Number = 1;
var frames:int = 150;

// Pushing a bunch of point objects onto the array is a neater
// method than using a multi-dimensional array. If you want the clarity of the 
// index to help with debugging you could also do this: 
// numbers[0] = new Point(460, 100);
var numbers:Array = [];
numbers.push(new Point(460, 100));
numbers.push(new Point(10, 20));
numbers.push(new Point(10, 100));
numbers.push(new Point(10, 180));
numbers.push(new Point(160, 20));
numbers.push(new Point(160, 100));
numbers.push(new Point(160, 180));
numbers.push(new Point(310, 20));
numbers.push(new Point(310, 100));
numbers.push(new Point(310, 180));

var fullDate:String = "271524";

// Vector for shapes seems overkill unless you need to loop over 
// your shapes again later. For now, we store a reference to the 
// current shape only
var shape:Shape; 

// Set up the first line
drawLine();

// Probably easier to run a single enter frame for the duration of the whole animation
this.addEventListener(Event.ENTER_FRAME, tick);

function drawLine(time:Number = 120):void {

    // Get the appropriate index for start and end points in the numbers array
    var startIndex:int = int(fullDate.charAt(count));
    var endIndex:int = int(fullDate.charAt(count + 1));

    startPoint = Point(numbers[startIndex]);
    endPoint = Point(numbers[endIndex]);    

    // create a new shape and add it to stage
    shape = new Shape();
    this.addChild(shape);

    frames = time;
    prog = 0;
}

function drawLineTick(progress:Number):void{
    shape.graphics.clear();
    shape.graphics.lineStyle(14,0x2dfdfd);

    shape.graphics.moveTo(startPoint.x,startPoint.y);
    shape.graphics.lineTo(startPoint.x + ((endPoint.x - startPoint.x) * progress), startPoint.y + ((endPoint.y - startPoint.y) * progress));
}

function tick(e:Event):void {
    drawLineTick(prog / frames);    
    prog += bonus;

    // Finished drawing a shape
    if(prog >= frames){
        // Increment count, reset progress and set up the next line
        count ++;
        prog = 0;
        drawLine();
    }

    // Finished drawing all shapes
    if (count == fullDate.length + 1) {
        // Good practice to remove the eventlistener when finished
        this.removeEventListener(Event.ENTER_FRAME, tick);
    }
} 

Upvotes: 2

Related Questions