I'm very new to blitting, and I'm still trying to understand the process. In my View
object, I have this in my constructor;
this.bcg = new BitmapData(800,600,false,0x000000);
this.canvas = new Bitmap(bcg);
Then I add it to the stage;
addChild(canvas);
Then inside my main game loop, I iterate through a nested array to blit copies of rect
of type BitmapData
objects;
if (array[i][j] !=0) {
canvas.bitmapData.copyPixels(rect, rect.rect, new Point(i, j));
}
I thought perhaps I could do it by blitting by background back onto canvas
before my loop;
canvas.bitmapData.copyPixels(bcg, bcg.rect, new Point(0, 0));
But that doesn't work. I've tried searching around for an answer for this, but it's very difficult to find any in-depth information on blitting in AS3.
What I'm trying to do is clear the bitmap of all the pixels I've blitting onto it, and start again with just my background, bcg
. I tried doing this before my loop;
this.bcg = new BitmapData(800,600,false,0x000000);
this.canvas = new Bitmap(bcg);
But I ended up with a completely black screen, and none of my rect
were being blitted onto canvas
.
Here's a simple blitting example:
private var m_bg:BitmapData = new BitmapData( 400, 300, false, 0xffff0000 ); // simple solid red colour
private var m_canvas:BitmapData = new BitmapData( 400, 300, true, 0x00000000 ); // the canvas that we're drawing into
private var m_obj:BitmapData = new BitmapData( 20, 20, false, 0xff00ff00 ); // simple green square
private var m_objDrawPos:Point = new Point; // where we'll draw our obj
private var m_objDir:Point = new Point; // the direction that our obj is moving in
private var m_objSpeed:Number = 20.0; // the speed of our obj
public function Main()
{
// create the bitmap for our canvas and add it to the stage
var b:Bitmap = new Bitmap( this.m_canvas );
this.addChild( b );
// set our initial direction
this.m_objDir.setTo( 1.0, 1.0 ); // diagonal right
// add our enter frame
this.addEventListener( Event.ENTER_FRAME, this._onEnterFrame );
}
private function _onEnterFrame( e:Event ):void
{
// move our object by changing it's draw position
this.m_objDrawPos.x += this.m_objDir.x * this.m_objSpeed;
this.m_objDrawPos.y += this.m_objDir.y * this.m_objSpeed;
// simple bounds change, to reflect the object
if ( this.m_objDrawPos.x < 0 || this.m_objDrawPos.x + this.m_obj.width > this.m_canvas.width )
this.m_objDir.x *= -1;
if ( this.m_objDrawPos.y < 0 || this.m_objDrawPos.y + this.m_obj.height > this.m_canvas.height )
this.m_objDir.y *= -1;
// copy our this.m_bg - this will erase all previous changes
// NOTE: depending on what your bg is, you can all use fillRect() if it's a solid colour
// NOTE: passing new Point() as the destPoint, will mean that our bg will always be drawn
// in the top-left of the canvas. As this never changes - you can keep this as a variable
this.m_canvas.copyPixels( this.m_bg, this.m_bg.rect, new Point );
// copy our object to its new position
this.m_canvas.copyPixels( this.m_obj, this.m_obj.rect, this.m_objDrawPos );
}
What you need to know about blitting, is that it's the position passed in as destPoint
that determines the top-left position of the BitmapData
that you're blitting - think of it as the x
and y
of a normal DisplayObject
- (0,0)
will mean that it's drawn in the top left, while (canvas.width - obj.width, canvas.height - obj.height)
will mean that it's drawn in the bottom right.
To make your life easier, create a simple class to store all this data for you. Something like:
public class BlitObj
{
/************************************************************/
private var m_bmd:BitmapData = null; // our BitmapData graphics
private var m_offset:Point = null; // the offset (how we manage the reference point)
private var m_drawPos:Point = null; // our draw position for when we're blitting the object
private var m_position:Point = null; // the position of our object, in relation to the reference point
/************************************************************/
/**
* The position of the BlitObj, in relation to the reference point
*/
public function get position():Point { return this.m_position; }
/**
* The BitmapData graphics that we're going to blit
*/
public function get blitGraphics():BitmapData { return this.m_bmd; }
/**
* The position to blit this BlitObj at (top-left corner)
*/
public function get blitDestPos():Point { return this.m_drawPos; }
/************************************************************/
/**
* Creates a new BlitObj
* @param bmd The graphics for this BlitObj
* @param offset The offset to our registration point
*/
public function BlitObj( bmd:BitmapData, offset:Point = null )
{
this.m_bmd = bmd;
this.m_offset = ( offset == null ) ? new Point : offset;
this.m_drawPos = new Point( -this.m_offset.x, -this.m_offset.y );
this.m_position = new Point;
}
/**
* Sets the position of the BlitObj (in relation to its reference point)
* @param x The x position of the object
* @param y The y position of the object
*/
public function setPos( x:Number, y:Number ):void
{
this.m_position.setTo( x, y );
this.m_drawPos.setTo( x - this.m_offset.x, y - this.m_offset.y ) ;
}
}
One thing to watch for when blitting, and one this this class does, it handle the offset
. When you provide a destPoint
to the copyPixels()
function, it's the position to place the top-left of your BitmapData
before drawing it. Often, however, you want your object to have a different reference point that the top left (e.g, a circle will have its reference point in the middle). This lets you handle that.
// create our circle graphics with their registration point in the center
var circleBMD:BitmapData = ...; // get the graphics for your circle
var circle:BlitObj = new BlitObj( circleBMD, new Point( circleBMD.width * 0.5, circleBMD.height * 0.5 ) );
circle.setPos( this.stage.stageWidth * 0.5, this.stage.stageHeight * 0.5 ); // center it on the stage
// now you can draw it:
canvas.copyPixels( circle.blitGraphics, circle.blitGraphics.rect, circle.blitDestPos );