wanghe513120 发表于 2012-6-28 08:31:07

Flash AS3教程:位图用于碰撞检测

现在来看如何用位图实现碰撞检测。首先需要一个适当的不规则形状来完成测试,五角星就很合适,可以建立一个五角星类以便以后重用。以下就是Star类:
package
import Flash.display.Sprite;
public class Star extends Sprite
{
public function Star(radius:Number, color:uint = OxFFFFOO):void
{
graphics.lineStyle(o);
graphics.moveTo(radius, 0) ;
graphics.beginFill(color);
// draw 10 lines
for(var i:int = 1; i < 11; i++)
{
var radius2:Number = radius;
if(i % 2 ) 0)
{
// alternate radius to make spikes every other line
radius2 = radius / 2;
}
var angle:Number = Math.PI * 2 / 10 * i;
graphics.lineTo(Math.cos(angle) * radius2, Math.sin(angle) * radius2);
}
}
}
}
这里只是画出角度不断递增而且半径交替变化的一系列线条,从而巧妙地构成了一个五角星。下面这个类可以完成碰撞测试。类似于本书中的大多数代码,这个类可以作为一个文档类在FlashCS3或CS4中使用,也可以作为主应用类在Flex Bui1der 3或4中使用,同样也可以从本书网站下载得到。
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.MouseEvent;
import flash.filters.GlowFilter;
import flash.geom.Matrix;
import flash.geom.Point;
public class BitmapCollision1 extends Sprite
{
private var bmpd1:BitmapData;
private var bmp1:Bitmap;
private var bmpd2:BitmapData;
private var bmp2:Bitmap;
public function BitmapCollision1()
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
// make a star
var star:Star = new Star(SO);
// make a fixed bitmap, draw the star into it
bmpd1 = new BitmapData(100, 100, true, O);
bmpd1.draw(star, new Matrix(1, 0, 0, 1, 50,50)) ;
bmp1 = new Bitmap(bmpd1);
bmp1.x = 200;
bmp1.y = 200;
addChild(bmp1);
// make a moveable bitmap, draw the star into it, too
bmpd2 = new BitmapData(100, 100, true, 0);
bmpd2.draw(star, new Matrix(l, 0, 0, 1, 50, 50));
bmp2 = new Bitmap(bmpd2);
addChild(bmp2);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMoving);
}
private function onMouseMoving(event:MouseEvent):void
{
// move bmp2 to the mouse position (centered).
bmp2.x = mouseX - 50;
bmp2.y = mouseY - 50;
// the hit test itself.
if(bmpd1.hitTest(new Point(bmp1.x, bmp1.y), 255, bmpd2, new Point(bmp2.x, bmp2.y), 255))
{
bmp1.filters = ;
bmp2.filters = ;
}
else
{
bmp1.filters = [];
bmp2.filters = [];
}
}
}
}
这里使用Star类创建了一个五角星,并分别绘制在两个位图中。我们使用了一个矩阵从而在绘制时将五角星在各个轴上分别偏移到个像素,因为五角星的对准点位于其中心,而位图的对准点位于左上角。通过偏移就可以看到整个五角星。
其中一个位图Cbmpl)位于场景中的固定位置,另一个位图Cbmp2) 设置为跟随鼠标移动。 这里的关键代码如下所示:
if(bmpd1.hitTest(new Point(bmp1.x, bmp1.y) , 255, bmpd2, new Point(bmp2.x, bmp2.y), 255))
正是这段代码确定了两个位图是否接触。BitmapData.hitTest方法的签名如下:
hitTest(firstPoint:Point,
firstAlphaThreshold:uint,
secondObject:Object,
secondPoint:Point ,
secondAlphaThreshold:uint);
注意到,参数可分为两组: 分别以first和second开头①。要分别为其提供一个点值(第一个点和第二个点) ,这对应于BitmapData 的左上角。之所以这样做,其原因在于各个位图有可能嵌套在另一个实体中,或者可能深深地嵌套在多重实体中。在这种情况下,它们可能在完全不同的坐标系统 中。如果有必要,可以使用DisplayObject . localToGlobal 方法指定一个任意点将两个坐标系统对齐。不过,在这个例子中,两个位图正好放在场景上,所以可以直接使用其局部位置来构造各自的点。
下一组first/last参数对应α阙值。前面已经了解到,在一个透明的时tmapData 中,各像素的透明度取值范围可以从o (完全透明〉到255 (完全不透明〉。α阑值参数指定了像索要有怎样的不透明度才能算一次碰撞。在这个例子中,我们将两个α阑值都设置为255 ,这表示对于任一位图中的像素,要认为它通过了碰撞测试,那么这个像素必须完全不透明。稍后还会介绍另一个例子,展示使用较低闽值的情况。
最后,这里还有一个secondObject参数。需要注意,这个参数的类型指定为对象(Object)。这里可以使用Point 、Rectangle或者另一个BitmapData作为测试对象。如果使用Point或Rectangle ,那么就不再需要使用最后两个参数。如果希望测试鼠标是否接触到一个位图,就可以用一个Point 进行测试,这很有用。下面是一个简单的例子:
if(myBitmapData.hitTest(new Point(myBitmapData.x, myBitmapData.y), 255, new Point(mouseX, mouseY)))
{
// mouse is touching bitmap
}
我想不出特别有用的例子来展示如何用一个矩形测试位图,不过要知道确实可以这样做。如果需要,你完全可以利用矩形完成位图测试。不过在我们的例子中使用了另一个时tmapData对象,所以还要传入第二个Point和α阔值。
最后,如果出现碰撞,就使用一个默认的发光滤镜为各五角星指定一个红色发光光环。如果没有碰撞,则删除所有滤镜。可以看到的结果如图1-3和图1 -4所示。

图1-3 五角星未接触图

图1-4 现在五角星发生碰撞
可以做一些尝试,你会看到这确实是像素与像素间的碰撞检测。

无极灯小周 发表于 2012-6-28 11:55:20

谢谢分享

小虎仔 发表于 2012-6-30 16:57:39

挺好啊挺好

新向明月 发表于 2012-7-4 13:20:01

帮顶帮顶帮顶
页: [1]
查看完整版本: Flash AS3教程:位图用于碰撞检测