【问题标题】:How do I clear the bitmap each time before blitting?如何在每次 blitting 之前清除位图?
【发布时间】:2015-01-04 11:51:23
【问题描述】:

我对 blitting 还很陌生,我仍在努力理解这个过程。在我的View 对象中,我的构造函数中有这个;

this.bcg = new BitmapData(800,600,false,0x000000);
this.canvas = new Bitmap(bcg);

然后我把它添加到舞台上;

addChild(canvas);

然后在我的主游戏循环中,我遍历一个嵌套数组来 blit 类型为 BitmapData 对象的 rect 副本;

if (array[i][j] !=0) {
        canvas.bitmapData.copyPixels(rect, rect.rect, new Point(i, j));
}

我想也许我可以在循环之前通过背景返回到canvas 来做到这一点;

canvas.bitmapData.copyPixels(bcg, bcg.rect, new Point(0, 0));

但这不起作用。我已经尝试四处寻找答案,但很难找到任何有关 AS3 中的 blitting 的深入信息。

我想要做的是清除所有像素的位图,然后从我的背景重新开始,bcg。我在循环之前尝试过这样做;

this.bcg = new BitmapData(800,600,false,0x000000);
this.canvas = new Bitmap(bcg);

但我最终得到了一个完全黑屏,我的rect 没有一个被转移到canvas

【问题讨论】:

  • blitting 你的对象有用吗?如果这样可行,那么没有理由不使用 blitting 你的背景图片

标签: actionscript-3 bitmap bitmapdata


【解决方案1】:

下面是一个简单的 blitting 示例:

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 );
}

关于 blitting,您需要了解的是,作为 destPoint 传入的位置决定了您要进行 blitting 的 BitmapData 的左上角位置 - 将其视为 x 和 @普通DisplayObject 的987654325@ - (0,0) 表示绘制在左上角,而(canvas.width - obj.width, canvas.height - obj.height) 表示绘制在右下角。

为了让您的生活更轻松,请创建一个简单的类来为您存储所有这些数据。比如:

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 ) ;
    }
}

blitting 时需要注意的一件事,这个类做的一件事,它处理offset。当您向copyPixels() 函数提供destPoint 时,它是在绘制之前放置BitmapData 左上角的位置。然而,通常你希望你的对象有一个与左上角不同的参考点(例如,一个圆的参考点在中间)。这可以让您处理。

// 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 );

【讨论】:

  • 这是一个很好的解释。谢谢你。我不太明白的唯一部分是为什么你在构造函数中将 m_drawPos 设置为负 m_offset.x 和负 m_offset.y。对吗?
  • 如果我们设置一个偏移量,这只是为了让初始的m_drawPos 正确 - 想象一下我们希望我们的参考点(以及我们的位置)成为中心的圆。当我们绘制时,我们需要传递我们正在绘制的 BMD 的左上角的位置,在位置(0,0),将是负偏移量(即左上角总是position - offset)跨度>
  • 如果它更清楚,您可以将m_offset重命名为m_referencePoint
  • 我现在明白了。我只需要在逻辑上遵循它。 Blitting 对我来说很新鲜。我会看看我是否可以编写自己的 BMD 包装器,类似于你的。然后我就知道我完全理解了这个过程。
  • 没问题;如果您遇到任何麻烦,只需在 SO 上发布另一个问题,或直接联系 :)
【解决方案2】:

我现在知道自己做错了什么。

这行得通;

this.bcg = new BitmapData(800,600,false,0x000000);
canvas.bitmapData.copyPixels(bcg, bcg.rect, new Point(0, 0));

我不得不重新声明bcg然后将它传递给canvas。因为我的rect 对象被转移到bcg,对吗?我正在使用它创建位图;

this.canvas = new Bitmap(bcg);

所以 canvas 持有对 bcg 的引用?

【讨论】:

  • 这是在每帧创建一个新的BitmapData,效率非常低,很快就会耗尽你的内存
猜你喜欢
  • 2019-01-14
  • 2015-04-09
  • 1970-01-01
  • 2017-04-26
  • 1970-01-01
  • 2021-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多