开发者

BitmapData.draw() Matrix problem

I've run into an issue where the BitmapData.draw() method isn't accurately subtracting image data from a .png that uses transparency.

I've put together a test file that shows this behavior, it's located here: http://www.filedropper.com/shield_1

In a nutshell, a sprite drops from the top of the screen and when it intersects with a sprite at the bottom of the screen, the sprite that was dropping takes out a chunk of the sprite at the bottom. I've got all of this working except that when i reset the x and y position of the sprite after its intersected the bottom sprite and it intersects with the bot开发者_如何学Ctom sprite again, it doesn't take the same size chunk out of the sprite at the bottom.

I apologize if I'm not explaining this well enough. If you a moment to look at the file I posted it will make sense.

Here's the code which requires two png files within the library with Linkage values of ShieldBase and SnowBall.

package 
{

 import flash.display.Sprite;
 import flash.display.Bitmap;
 import flash.display.BitmapData;
 import flash.display.BlendMode;
 import flash.geom.Point;
 import flash.geom.Matrix;
 import flash.geom.Rectangle;
 import flash.events.Event;

 public class Shield extends Sprite
 {

  public var baseBmpData:BitmapData = new ShieldBase(0,0);
  public var baseBmp:Bitmap = new Bitmap(baseBmpData);
  public var missileBitmapData:BitmapData = new SnowBall(0,0);
  public var missileBitmap:Bitmap = new Bitmap(missileBitmapData);

  public var missileMatrix:Matrix = new Matrix();

  public function Shield()
  {

   baseBmp.y = 300;
   baseBmp.x = 40;
   stage.addChild(baseBmp);

   missileBitmap.x = 85;
   missileBitmap.y = 0;
   stage.addChild(missileBitmap);

   stage.addEventListener(Event.ENTER_FRAME, dropFromSky);

  }

  public function dropFromSky(e:Event)
  {

   for (var i:int=0; i<10; i++)
   {

    if (baseBmpData.hitTest(new Point(baseBmp.x,baseBmp.y),0x00,new Point(missileBitmap.x,missileBitmap.y)))
    {

     missileBitmap.y++;

     missileMatrix = new Matrix();
     missileMatrix.translate(baseBmp.x,baseBmp.y);
     missileMatrix.tx = (missileBitmap.x - baseBmp.x);
     missileMatrix.ty = (missileBitmap.y - baseBmp.y);

     // public function draw(source:IBitmapDrawable, matrix:Matrix = null, colorTransform:flash.geom:ColorTransform = null, blendMode:String = null, clipRect:Rectangle = null, smoothing:Boolean = false):void
     baseBmpData.draw(missileBitmap, missileMatrix, null, BlendMode.ERASE, null, true);

     missileBitmap.x = rand(60, 140);
     missileBitmap.y = 0;
    }
    else
    {
     missileBitmap.y++;
    }

   }

  }

  public function rand(low:Number=0, high:Number=1):Number
  {
   return Math.floor(Math.random() * (1+high-low)) + low;
  }


 }

}

I think the issue is with either the hitTest and/or BitmapData.draw() not working as expected.

many thanks,

devin


There are two problems.

1) The position that you test for the collision; if you use the center of the ball instead of the top-left then it works properly.

2) The drop shadow on your shield :
What happens is that the pixels on the edge of the shadow that are barely visible are causing the hitTest to succeed; I would suggest you remove the drop shadow from the image and apply it using an actual drop-shadow filter in flash. To get it to work with the drop shadow I changed the alpha threshold in the hitTest to 128 so that the semi-transparent pixels of the drop shadow are ignored. You could leave the threshold at 0 but it looks odd at the beginning when the ball seemingly hits nothing.

Change this:

baseBmpData.hitTest(new Point(baseBmp.x,baseBmp.y),0x00,new Point(missileBitmap.x,missileBitmap.y))

to this:

baseBmpData.hitTest(new Point(baseBmp.x,baseBmp.y),128,new Point(missileBitmap.x+missileBitmap.width*0.5,missileBitmap.y+missileBitmap.height*0.5))
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜