Skip to main content
Participant
November 10, 2010
Question

create a shape tween of two graphics

  • November 10, 2010
  • 1 reply
  • 1080 views

Hello,

I am attempting to create a shape tween on the fly.

I have two bitmap graphics (bmp1, bmp2) already created with the BitmapData class using the contents of an object (label1):

var myBitmapData1:BitmapData = new BitmapData(150, 150);

myBitmapData1.draw(label1, matrix, null, null, null, true);

var bmp1:Bitmap = new Bitmap(myBitmapData1);

What I want to do is take bmp1 and bmp2, and create a shape tween on the fly with those two bitmaps.

Then be able to step back and forth along the timeline of that new shape tween.

How do I go about doing this?

I've been searching and trying for a few days now and can't find any way to create the shape tween on the fly with essentially two variable objects.

Thanks for any help you can offer,

George

This topic has been closed for replies.

1 reply

kglad
Community Expert
Community Expert
November 10, 2010

you can loop through the pixels of the start bitmap while checking the pixels of the end bitmap.  change the start bitmap pixels to match the end bitmap pixels if they are different.

check:   www.kglad.com, snippets, shape tween.

Participant
November 11, 2010

Okay, wow, did you just whip that up, or did you have the same idea at some point??

And how do I go about doing that?

I'd want to use a slider to control the timeline of the shape tween.

Can you point me in the right direction with some code?

That was awesome!!

kglad
Community Expert
Community Expert
November 11, 2010

here it is in as2.   there won't be too many changes for as3 because most of it is dealing with the bitmapdata class which is the same in as2 as as3:

dep = 0;
function bmpSetup(mc) {
    if (!bmpA) {
        bmpA = [];
    }
    bmp = _root["bmp"+dep]=new BitmapData(mc._width, mc._height, true, 0xff0000);
    var mat = new Matrix();
    mat.tx = -startX;
    mat.ty = -startY;
    var ct:ColorTransform = new ColorTransform(1, 1, 1, 1, 0, 0, 0, 0);
    bmp.draw(mc, mat, ct);
    mc1 = _root.createEmptyMovieClip("mc"+dep, dep++);
    mc1.attachBitmap(bmp, dep);
    bmpA.push([bmp, mc1, startX, startY, mc]);
    mc1._x = startX;
    mc1._y = startY;
    mc._visible = 0;
}
function resizeF() {
    // resize movieclip, then make new bmp of this start movieclip
    bmpA[0][4]._width = .5*(bmpA[0][4]._width+bmpA[1][4]._width);
    bmpA[0][4]._height = .5*(bmpA[0][4]._height+bmpA[1][4]._height);
    var mat = bmpA[0][4].transform.matrix;
    bmpA[0][4]._x = -bmpA[0][2]*(mat.a-1);
    bmpA[0][4]._y = -bmpA[0][3]*(mat.d-1);
    if (Math.abs(bmpA[0][4]._width-bmpA[1][4]._width)<1 && Math.abs(bmpA[0][4]._height-bmpA[1][4]._height)<1) {
        bmpA[0][4]._visible = 0;
        bmpA[0][4]._width = bmpA[1][4]._width;
        bmpA[0][4]._height = bmpA[1][4]._height;
        clearInterval(resizeI);
        resizeBMPF();
    }
    updateAfterEvent();
}
function resizeBMPF() {
    // new bmp for the resized movieclip
    bmp = _root["bmp"+dep]=new BitmapData(800, 600, true, 0xff0000);
    var mat = bmpA[0][4].transform.matrix;
    mat.tx = -bmpA[0][2]*(mat.a-1);
    mat.ty = -bmpA[0][3]*(mat.d-1);
    var ct:ColorTransform = new ColorTransform(1, 1, 1, 1, 0, 0, 0, 0);
    bmp.draw(bmpA[0][4], mat, ct);
    mc1 = _root.createEmptyMovieClip("mc"+dep, dep++);
    mc1.attachBitmap(bmp, dep);
    bmpA[0][4]._visible = 0;
    bmpA[0][0] = bmp;
    contractionLoopF();
}
function contractionLoopF() {
    // now tween the same-sized bmps
    // define contractionLoopA, the array of points that should be looped for contraction
    contractionLoopA = [];
    // loopIndex incremented in tweenF()
    contractionIndex = 0;
    xleft = bmpA[0][2];
    xright = xleft+bmpA[0][4]._width;
    ytop = bmpA[0][3];
    ybottom = Math.ceil(bmpA[0][3]+bmpA[0][4]._height);
    loopLength = Math.min(bmpA[0][4]._width, bmpA[0][4]._height);
    // exclude points in contraction perimeter that are outside of all contraction points
    for (var i = 0; i<=loopLength; i++) {
        // add an element to loopA.  each element is a set of points defining a rectangle centered around the middle of bmpA[0][0]. corners r duplicated but not a problem.
        pointsA = [];
        for (var j = xleft; j<=xright; j++) {
            pointsA.push([j, ytop]);
            pointsA.push([j, ybottom]);
        }
        for (var k = ytop; k<=ybottom; k++) {
            pointsA.push([xleft, k]);
            pointsA.push([xright, k]);
        }
        contractionLoopA.push(pointsA);
        xleft++;
        xright--;
        ytop++;
        ybottom--;
        if (xleft>xright || ytop>ybottom) {
            break;
        }
    }
    expansionLoopF();
}
function expansionLoopF() {
    // find border points that are expansion points.
    if (!expansionInitialized) {
        expansionInitialized = 1;
        expansionPointObj = new Object();
        // 1.  create array of expansion points. 
        // 2.  loop through this array looking for "outside" border points.  as border points found and remove them from expansion point array and store them in a nextExpansionPointsA point array. 
        // 3.  expand into points in nextExpansionPointsA.
        // 4.  set ExpansionPointsA=nextExpansionPointsA
        // 4.5 reset nextExpansionPointsA
        // 5.  loop through ExpansionPointsA for points that have a border point in expansionPointA.  if found add to nextExpansionPointsA and remove from expansionPointA
        xleft = bmpA[0][2];
        xright = xleft+bmpA[0][4]._width;
        ytop = bmpA[0][3];
        ybottom = Math.ceil(bmpA[0][3]+bmpA[0][4]._height);
        for (var x = xleft; x<=xright; x++) {
            for (var y = ytop; y<=ybottom; y++) {
                if (expansionPointF(bmpA[0][0], bmpA[1][0], x, y)) {
                    expansionPointObj[x+","+y] = true;
                }
            }
        }
    }
    // 1.  done                                        
    if (!nextExpansionPointsA) {
        // no border points yet.  loop through all expansion pts looking for border points
        nextExpansionPointsA = [];
        // check expansionPointsA for point that's an outside border point
        for (obj in expansionPointObj) {
            var x = Number(obj.substring(0, obj.indexOf(",")));
            var y = Number(obj.substring(obj.indexOf(",")+1));
            if (outsideBorderPointF(bmpA[0][0], x, y)) {
                nextExpansionPointsA.push([x, y]);
                delete expansionPointObj[x+","+y];
            }
        }
    } else {
        // nextExpansionPointsA already defined
        // now can loop through all previous border points looking for next border points
        previousExpansionPointsA = nextExpansionPointsA;
        nextExpansionPointsA = [];
        for (var index = 0; index<previousExpansionPointsA.length; index++) {
            var x = previousExpansionPointsA[index][0];
            var y = previousExpansionPointsA[index][1];
            borderPointF(bmpA[0][0], x, y);
        }
    }
    //trace(nextExpansionPointsA.length+" "+(getTimer()/1000));
    if (nextExpansionPointsA.length>0) {
        tweenI = setInterval(tweenF, 10);
    }
}
function borderPointF(bmp, x, y) {
    // x,y is an inside border point
    // check if any border points are in expansionPointObj
    // if so, add to nextExpansionPointsA and remove from expansionPointsObj
    for (var xinc = -1; xinc<=1; xinc++) {
        for (var yinc = -1; yinc<=1; yinc++) {
            if (xinc != 0 || yinc != 0) {
                if (expansionPointObj[(xinc+x)+","+(yinc+y)]) {
                    nextExpansionPointsA.push([xinc+x, yinc+y]);
                    delete expansionPointObj[(xinc+x)+","+(yinc+y)];
                }
            }
        }
    }
}
function outsideBorderPointF(bmp, x, y) {
    // these points are outside.  check to see if they are border points
    for (var xinc = -1; xinc<=1; xinc++) {
        for (var yinc = -1; yinc<=1; yinc++) {
            if (xinc != 0 || yinc != 0) {
                if (bmp.getPixel32(x+xinc, y+yinc) != 0) {
                    return true;
                }
            }
        }
    }
    return false;
}
function expansionPointF(bmpStart, bmpEnd, x, y) {
    var bmpEndPixColor = bmpEnd.getPixel32(x-bmpA[0][2], y-bmpA[0][3]);
    if (bmpStart.getPixel32(x, y) != bmpEndPixColor && bmpEndPixColor != 0) {
        return true;
    } else {
        return false;
    }
}
function tweenF() {
    clearInterval(tweenI);
    for (var ptsIndex = 0; ptsIndex<contractionLoopA[contractionIndex].length; ptsIndex++) {
        var x = contractionLoopA[contractionIndex][ptsIndex][0];
        var y = contractionLoopA[contractionIndex][ptsIndex][1];
        if (bmpA[0][0].getPixel(x, y) != 0 && bmpA[1][0].getPixel(x-bmpA[0][2], y-bmpA[0][3]) == 0) {
            //bmpA[0][0].setPixel32(x, y, "0x"+bmpA[1][0].getPixel32(x-bmpA[0][2], y-bmpA[0][3]).toString(16));
            bmpA[0][0].setPixel32(x, y, "0x00000000");
        }
    }
    for (var ptsIndex = 0; ptsIndex<nextExpansionPointsA.length; ptsIndex++) {
        var x = nextExpansionPointsA[ptsIndex][0];
        var y = nextExpansionPointsA[ptsIndex][1];
        bmpA[0][0].setPixel32(x, y, "0x"+bmpA[1][0].getPixel32(x-bmpA[0][2], y-bmpA[0][3]).toString(16));
    }
    contractionIndex++;
    if (lengthF(expansionPointObj)) {
        expansionLoopF();
    } else if (contractionIndex<contractionLoopA.length) {
        tweenI = setInterval(tweenF, 10);
    }
    updateAfterEvent();
}