如何在使用draw方法时旋转BitmapData。宽度高度限制剪裁/裁剪问题

时间:2010-01-29 20:52:12

标签: flash actionscript-3 actionscript

我编写了一个使用BitmapData.hitTest工作的碰撞检测类。基本上,每次更新时,调用.draw方法,然后两个BitmapData相互命中,以查看是否存在冲突。

它工作得很好,但是如果我开始旋转我用于BitmapData的源MovieClip,则转换不会在draw方法中注册。所以我所做的是在draw方法中通过Matrix。这样可行。但这是实际问题。如果我将BitmapData输出到舞台上的Bitmap,我看到Bitmap 实际上是旋转,但现在它超出了BitmapData的边界(宽度和高度)。这是裁剪/剪裁源MovieClip的图像。

我的第一个猜测是旋转BitmapData,但似乎不可能旋转。没有任何属性可以帮助你解决这个问题。还有另一种方式吗?

UPDATE :基本上,当MovieClip的Bitmap克隆旋转到正坐标空间之外时,它不会被绘制。它在BitmapData设置的宽度和高度范围之外旋转。我可以将边界乘以2,然后将位图置于集合边界内,但随后原点永远不会被固定,对象总是被移动。效果很好,但是将对象与任何特定点对齐都不可能。

这是我的孤立测试代码。它要求您在名为“iTest”的舞台上安装MovieClip。我使用了一个相当垂直的箭头形状(高于它的宽度),所以我可以直观地跟踪旋转并帮助突出剪裁问题:

var rotateTimer:Timer = new Timer(10);

function rotateObject_init():void
{
 rotateTimer.addEventListener(TimerEvent.TIMER, rotateObject);
 rotateTimer.start();
}

function rotateObject_stop():void
{
 rotateTimer.removeEventListener(TimerEvent.TIMER, rotateObject);
 rotateTimer.stop();
}

function rotateObject(_event:TimerEvent):void
{
 // Deletes the previous bitmap
 if (this.getChildByName("iTestClone") != null)
 {
  removeChild(this.getChildByName("iTestClone"));

  testClone = null;
  testData = null;
 }

 iTest.rotation += 1;

 // Capture source BitmapData
 var testData:BitmapData = new BitmapData(iTest.width, iTest.height, false, 0xFFFFFF); 

 // Capture source transformations
 var testMatrix:Matrix = new Matrix();
 testMatrix.scale(iTest.scaleX, iTest.scaleY);
 testMatrix.rotate( iTest.rotation * (Math.PI / 180) );
 testMatrix.translate(0, 0);

 // Draw source with matrix
 testData.draw(iTest, testMatrix);

 // Output Bitmap
 var testClone:Bitmap = new Bitmap(testData);
 testClone.name = "iTestClone";
 testClone.transform = testMatrix.tra
 addChild(testClone);

 // Always makes sure source is visible
 this.swapChildren(iTest, testClone);
}

rotateObject_init();

3 个答案:

答案 0 :(得分:4)

好问题!

我试图将一个正方形的BitmapData克隆旋转10度。为了获得位图数据的旋转,我使用了克隆对象的矩阵。正如您所提到的,问题是由于旋转枢轴而产生的偏移。

以下是我的看法:

bounds

为了解决这个问题,我认为如果我得到了BitmapData和最右边点之间的区别,那将给出x的偏移量,并为y做类似的操作,会让我在右边地点。

几乎,我看起来更好(只有一两个像素似乎受到伤害):

bounds 2

好的,我觉得我得到了:)

offset

该偏移是针对 x ,但他误导的是,它是由边界矩形的高度定义的,而不是宽度 。试试这个:

var box:Sprite = new Sprite();
box.graphics.lineStyle(0.1);
box.graphics.drawRect(0,0,150,100);
box.rotation = 10;
//get the size of the object rotated
var bounds:Rectangle = box.getBounds(this);
//make a bitmap data
var extra:int = 2;//cheating the trimmed pixels :)
var bitmapData:BitmapData = new BitmapData(bounds.width+extra,bounds.height+extra,false, 0x00009900);
//get the bottom left point
var bl:Point = getBottomLeft(box,bitmapData);
//get the matrix
var m:Matrix = box.transform.matrix;
//offset if
m.tx += Math.abs(bl.x);
//draw, using the offset, rotated matrix
bitmapData.draw(box,m);

var bitmap:Bitmap = new Bitmap(bitmapData);
bitmap.x = bitmap.y = 100;
addChild(bitmap);

function getBottomLeft(displayObject:DisplayObject,data:BitmapData):Point{
    var radius:int = displayObject.getBounds(displayObject).height;
    var angle:Number = displayObject.rotation * Math.PI / 180;
    var angle90:Number = angle + Math.PI * .5;
    return new Point(Math.cos(angle90) * radius, Math.sin(angle90) * radius);
}

在BitmapData构造函数中不需要绿色背景,这是用于调试的。 此外,您只需要左下角x位置,因此您需要返回一个数字而不是一个点。

因此稍短的版本将是:

var box:Sprite = new Sprite();
box.graphics.lineStyle(0.1);
box.graphics.drawRect(0,0,150,100);
box.rotation = 10;

var bounds:Rectangle = box.getBounds(this);
var extra:int = 2;//cheating the trimmed pixels :)
var bitmapData:BitmapData = new BitmapData(bounds.width+extra,bounds.height+extra,false, 0x00009900);

var m:Matrix = box.transform.matrix;
m.tx += Math.abs(getLeftmost(box,bitmapData));
bitmapData.draw(box,m);

var bitmap:Bitmap = new Bitmap(bitmapData);
bitmap.x = bitmap.y = 100;
addChild(bitmap);

function getLeftmost(displayObject:DisplayObject,data:BitmapData):Number{
    var radius:int = displayObject.getBounds(displayObject).height;
    var angle90:Number = displayObject.rotation * Math.PI / 180 + Math.PI * .5;
    return Math.cos(angle90) * radius;
}

结果:

offset 2

HTH,乔治

自我注意:小心你想要的^ _ ^

答案 1 :(得分:0)

您说bitmapData的边界导致裁剪,但您将边界设置为对象的宽度和高度。这表明返回的宽度和高度实际上是不正确的(即没有考虑旋转)。

也许尝试使用getBounds()来查找iTest的实际宽度和高度:

// Capture source BitmapData
var bounds:Rectangle = iTest.getBounds(iTest);
var testData:BitmapData = new BitmapData(bounds.width, bounds.height, false, 0xFFFFFF); 

我不完全确定这是否会起作用 - 我还没有测试过这些: - )

答案 2 :(得分:0)

只需使用rotation属性:

THENAMEOFMovieClip.rotation=number;

数字是您想要旋转的度数。