BitmapData.draw() 矩阵问题

发布于 2024-09-27 18:56:25 字数 2348 浏览 7 评论 0原文

我遇到了一个问题,即 BitmapData.draw() 方法无法准确地从使用透明度的 .png 中减去图像数据。

我已经整理了一个显示此行为的测试文件,它位于此处: http://www.filedropper.com/shield_1

简而言之,一个精灵从顶部掉落当它与屏幕底部的精灵相交时,掉落的精灵会带走底部精灵的一大块。我已经完成了所有这些工作,除了当我在与底部精灵相交后重置精灵的 x 和 y 位置并且再次与底部精灵相交时,它不会从精灵中取出相同大小的块底部。

如果我解释得不够好,我深表歉意。如果您花点时间看看我发布的文件,就会明白。

下面的代码需要库中的两个 png 文件,其链接值为 ShieldBase 和 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;
  }


 }

}

我认为问题在于 hitTest 和/或 BitmapData.draw() 未按预期工作。

非常感谢,

德文

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 bottom 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

子栖 2024-10-04 18:56:25

有两个问题。

1)您测试碰撞的位置;如果您使用球的中心而不是左上角,那么它可以正常工作。

2) 盾牌上的投影:
所发生的情况是,阴影边缘上几乎不可见的像素导致了
hitTest 成功;我建议您从图像中删除投影并使用 Flash 中的实际投影滤镜应用它。
为了让它与投影一起工作,我将 hitTest 中的 alpha 阈值更改为 128
以便忽略阴影的半透明像素。
您可以将阈值保留为 0,但一开始看起来很奇怪,因为球似乎没有击中任何物体。

将此:更改

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

为:

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

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))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文