Flash 使用draw方法时如何旋转位图数据。宽度-高度边界剪裁/裁剪问题

Flash 使用draw方法时如何旋转位图数据。宽度-高度边界剪裁/裁剪问题,flash,actionscript-3,actionscript,Flash,Actionscript 3,Actionscript,我编写了一个冲突检测类,该类使用BitmapData.hitTest工作。基本上,每次更新都会调用.draw方法,然后对两个BitmapData进行碰撞测试,以查看是否存在冲突 它工作得很好,但是如果我开始旋转用于BitmapData的源MovieClip,转换不会在draw方法中注册。所以我所做的就是在draw方法中通过一个矩阵。这很有效。但这是实际问题。如果我将BitmapData输出到舞台上的位图,我会看到位图实际上正在旋转,但现在它超出了BitmapData的边界(宽度和高度)。这是裁剪

我编写了一个冲突检测类,该类使用BitmapData.hitTest工作。基本上,每次更新都会调用.draw方法,然后对两个BitmapData进行碰撞测试,以查看是否存在冲突

它工作得很好,但是如果我开始旋转用于BitmapData的源MovieClip,转换不会在draw方法中注册。所以我所做的就是在draw方法中通过一个矩阵。这很有效。但这是实际问题。如果我将BitmapData输出到舞台上的位图,我会看到位图实际上正在旋转,但现在它超出了BitmapData的边界(宽度和高度)。这是裁剪/剪辑源电影剪辑的图像

我的第一个猜测是旋转位图数据,但旋转似乎不可能。没有任何属性可以帮助你实现这一点。还有别的办法吗

更新:基本上,当MovieClip的位图克隆在正坐标空间外旋转时,它不会被绘制。它在BitmapData集宽度和高度的边界之外旋转。我可以将边界乘以2,然后在设置的边界内将位图居中,但是原点永远不会固定,并且对象总是在移动。效果很好,但使对象无法与任何特定点对齐

这是我的独立测试代码。它要求你在舞台上有一个名为“iTest”的电影剪辑。我使用了一个相当垂直的箭头形状(高于它的宽度),因此我可以直观地跟踪旋转,并有助于突出剪裁问题:

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

您说位图数据的边界导致了剪切,但您将边界设置为对象的宽度和高度。这表明返回的宽度和高度实际上不正确(即未考虑旋转)

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

// Capture source BitmapData
var bounds:Rectangle = iTest.getBounds(iTest);
var testData:BitmapData = new BitmapData(bounds.width, bounds.height, false, 0xFFFFFF); 
不过,我不完全确定这是否有效——我还没有测试过任何一个:-)

好问题

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

下面是我的照片:

为了解决这个问题,我想如果我得到BitmapData的with和最右边的点之间的差,这将给出x的偏移量,对y进行类似的操作,将使我处于正确的位置

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

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

偏移量是指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;
}
结果:

嗯,乔治


自我提示:小心你想要的^ ^

只需使用旋转属性:

THENAMEOFMovieClip.rotation=number


数字是要旋转的度数。

也许您可以使用CDK()并完全避免这个问题?我宁愿使用自己的代码,这样我可以从经验中学习。另外,我真的不喜欢与其他人一起工作,因为人们有着如此不同的思维方式,我发现最好还是坚持自己的工作流程。谢谢你的链接,亲爱的,分享吧。我也可能有一个修复,我今晚可能可以尝试。基本上,你要做一个预曝光,需要将目标物体旋转360度,然后在这个过程中捕捉它的最大值和高度。使用它作为BitmapData大小,然后使用与您所做的类似的技术,但可能更简单,因为我们现在有了宽度和高度,并为位图计算出一个固定的左上角位置,当然,该位置符合BitmapData的范围。灵感来源于8BitLocket教程。getBounds的实现不错,但宽度和高度不是问题所在。事实上,一旦克隆的iTest位图在BitmapData的边界之外旋转,它就会被剪切。基本上,一旦它移动超过原点0,0。一旦它从0旋转到负片,你什么也看不到。希望这能解释清楚。啊,那没关系。我在想一个简单的例子,物体绕着它的中心旋转。。。显然不是这样。是的,我以前见过这种方法。这是一个皮蒂它只适用于盒子。尽管如此,我开始认为也许在我想要进行碰撞检测的物体上创建一个盒子是唯一的出路。一个通用的点击框,如果你愿意的话。我看不到任何其他的逻辑解决方案。我知道你的意思…我希望我知道算法,或者多一点几何学。