Joetjah
Joetjah

Reputation: 6132

Loop an image in Flash

I want to have a scene where an image which is 5000 pixels high is moving up 5 pixels each frame-refresh. When the image is all up, I'd like to see the top of the image connected to the bottom of the image. This should be done untill the level is 'done'. How can I 'loop' such an Image?

Upvotes: 1

Views: 682

Answers (2)

George Profenza
George Profenza

Reputation: 51837

You can create a copy of that image which you keep hidden/above and the trick is to update the position and loop accordingly so when one image goes bellow the screen it goes back on top and repeats.

Here's a basic snippet to illustrate the idea using the DisplayObject class and the scrollRect property:

//ignore this, you have your content already
var dummyContent:BitmapData = new BitmapData(100,100,false);
dummyContent.perlinNoise(10,10,8,12,true,true);

//important stuff starts here
var container:Sprite = addChild(new Sprite()) as Sprite;//make a container
container.scrollRect = new Rectangle(0,0,dummyContent.width,dummyContent.height);//set a scrollRect/'mask'
var part1:DisplayObject = container.addChild(new Bitmap(dummyContent));//add two copies
var part2:DisplayObject = container.addChild(new Bitmap(dummyContent));//of the same content
part2.y -= part2.height;//set the 2nd at the top of the 1st

addEventListener(Event.ENTER_FRAME,update);
function update(e:Event):void{
    //move both
    part1.y += 5;
    part2.y += 5;
    //check if any reach the bottom so they can be moved back up
    if(part1.y >= part1.height) part1.y = -part1.height;
    if(part2.y >= part2.height) part2.y = -part2.height;
    //the above can also be nicely placed in a loop if you plan on using more seamless looping clips/images
}

Obviously you will have different content, but the principle is the same.

If you're working with images, you can simply use BitmapData's copyPixels method:

var s:int = 5;//scroll speed
//make some content
var w:int = 100;
var h:int = 100;
var dummyContent:BitmapData = new BitmapData(w,h,false);
dummyContent.perlinNoise(10,10,8,12,true,true);

//prepare for stiching
var renderPos:Point = new Point();//position to render the current image to
var prenderPos:Point = new Point();//position to render the previous image (the 'hidden' copy above)
var render:BitmapData = new BitmapData(w,h,false);//create a bitmap data instance to render updated pixels int
addChild(new Bitmap(render));//and add it to the stage

addEventListener(Event.ENTER_FRAME,update);
function update(e:Event):void{
    renderPos.y = (renderPos.y+s)%h;//update the scroll position for the 1st part, % is used to loop back to 0 when the position gets to the content height
    prenderPos.y = renderPos.y - h;//update the scroll position for the 2nd part (above)
    render.lock();//freeze pixel updates
    render.copyPixels(dummyContent,dummyContent.rect,renderPos);//copy pixels from the scroll position to the bottom
    render.copyPixels(dummyContent,dummyContent.rect,prenderPos);//copy pixels from the top to the scroll position
    render.unlock();//unfreeze/update ALL THE PIXELS
}

You can try to use a Rectangle object which changes height (height-scrollPosition) so you potentially access less pixels each time or you can manually work out single for loops using BitmapData's getVector method, but that's something to look into if performance is actually an issue for such a simple task and it's worth checking what's faster ( copy full bitmap rect vs copy partial bitmap rect vs manually copy values using vector )

Upvotes: 1

Atriace
Atriace

Reputation: 2558

Be warned, Flash cannot load an image greater than 16,769,025 pixels (or 4095x4095). The height of 5000 pixels will work as long as the width is not greater than 3353.

That said, I'd loop the image by keeping two copies of the image onstage, move both at the same time with a parent object, and reset to origin once your loop point is met.

Consider the following stage setup:

Stage ¬
    0: MainTimeline:MovieClip ¬
        0: Container:MovieClip ¬
            0: img1:Bitmap
            1: img2:Bitmap

Now moving container up, you'd just need to check that the looping second image reaches the origin point of the first image.

function onEnterFrame(e:Event):void {
    Container.y = Container.y - 5;

    if (Container.y < -5000) {
        Container.y = -5;
    }
}

Upvotes: 1

Related Questions