Wrapping BitmapData in Actionscript 3

Posted on Friday, April 16th, 2010 at 11:00 pm by Hans Wichman

Pattern
Pattern Flash Example (mouseclick then cursor keys)

Sometimes you overlook the easiest solutions. I had implemented a wrapping bitmap in actionscript 2, by some complex copyPixels code, which would cut 1 to 4 pieces from the original image and put them together again, providing you with a bitmap that wraps.

Then I realized that there is a much easier solution, with more functionality as well (not only wrapping but tiling too). But surprised however that it performed much better too. Surprised because I would have thought that 4 copyPixel operations would have been faster than using the drawing API combined with beginBeginFill.

I’ve wrapped (no pun intended) the idea into two utility classes, the first WrappingBitmap is a simple sprite which takes a bitmapdata as source and creates a tiling wrapping display object that you can scroll.
The second is a WrappingBitmapData class which subclasses BitmapData and overrides the scroll method to wrap.

The demo is the pattern above, with the source image next to it. Click on the demo to give it focus and scroll using the cursor keys. You can see there is a quality difference, so you might want to change the bitmapfill smooth parameter to true.

You can download the example here: Wrappingbitmap (142).

package com.innerdrivestudios.visualeffect
{

import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.geom.Matrix;
import flash.geom.Point;

/**
* Implements a sprite that shows the source bitmap wrapped and allows you to scroll through it preserving the
* wrapping.
*
* @author JC Wichman
*/
public class WrappingBitmap extends Sprite
{
private var _bitmapdata:BitmapData = null;
private var _width:Number = 0;
private var _height:Number = 0;
private var _matrix:Matrix = null;

public function WrappingBitmap(pBitmapData:BitmapData, pWidth:Number = -1, pHeight:Number = -1, pOffset:Point = null)
{
_bitmapdata = pBitmapData;
_width = (pWidth > 0)?pWidth:pBitmapData.width;
_height =(pHeight> 0)?pHeight:pBitmapData.height;
_matrix = new Matrix();
if (pOffset != null) {
_matrix.tx = -pOffset.x;
_matrix.ty = -pOffset.y;
}
_paint();
}

private function _paint():void {
graphics.clear();
graphics.beginBitmapFill (_bitmapdata, _matrix, true, false);
graphics.drawRect (0, 0, _width, _height);
graphics.endFill();
}

public function scroll (dx:Number, dy:Number):void {
_matrix.tx += dx;
_matrix.ty += dy;
_paint();
}

public function scrollTo (x:Number, y:Number):void {
_matrix.tx = -x;
_matrix.ty = -y;
_paint();
}

public function grab(pDestination:BitmapData = null):BitmapData {
var lResult:BitmapData = pDestination || new BitmapData (_width, _height, _bitmapdata.transparent, 0);
lResult.draw (this);
return lResult;
}

}

}

package com.innerdrivestudios.visualeffect
{
import flash.display.BitmapData;
import flash.geom.Point;
/**
* Can be plugged in a bitmap, turning the bitmap into a wrapped scrolling bitmap, eg:
* bitmap.bitmapData = new WrappingBitmapData (bitmap.bitmapData);
*
* @author JC Wichman
*/
public class WrappingBitmapData extends BitmapData
{
private var _wrappingbitmap:WrappingBitmap = null;

public function WrappingBitmapData(pSource:BitmapData)
{
super (pSource.width, pSource.height, pSource.transparent, 0×0);

_wrappingbitmap = new WrappingBitmap (pSource);
_wrappingbitmap.grab (this);
}

override public function scroll (x:int, y:int) : void {
_wrappingbitmap.scroll (x, y);
_wrappingbitmap.grab(this);
}
}

}

3 Responses to “Wrapping BitmapData in Actionscript 3”

  1. Tim Says:

    Great info, thanks.

    The one thing I found is that the graphics.clear() function doesn’t clear the beginBitmapFill() from the previous call.

    If you have an image with sections that are totally transparent, they don’t get cleared out and you can see the old positions in the updated position (they bleed through).

    Any thoughts? Thanks again.

  2. Tim Says:

    I found the solution. In the ‘grab’ function of the WrappingBitmap, I needed this before the draw call:

    lResult.fillRect(lResult.rect, 0×0);

    Thanks again.

  3. Durss Says:

    Thanks for this usefull class :) !
    However, I just added thoses lines in the paint method :

    _matrix.tx = _matrix.tx % _width;
    _matrix.ty = _matrix.ty % _height;

    Indeed, there’s a really short limitation due to bitmapFill (i guess), if you go over something like 32.000, the scroll freezes. The matrix.tx value still grows but the scrolling is locked.
    Adding those lines prevents from that easily :)

    Thanks for this neat scrolling solution !

Leave a Reply