外门弟子
阅读权限 1
积分 551
侠名
UID 18802
主题
帖子
精华
好友
银子
金子
贡献
威望
推广
活跃
荣耀
注册时间 2020-2-20
最后登录 1970-1-1
在线时间 小时
个人主页
|
【游客模式】——注册会员,加入11RIA 闪客社区吧!一起见证Flash的再次辉煌……
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
转载:9RIA游戏开发者社区(天地会)
作者:ladeng6666(拉登大叔)
作者博客:http://www.ladeng6666.com/blog/
【Box2D系列教程-导航帖】—拉登大叔出品(总贴)
上一节课,我们学会了用b2Body的isSensor属性制作一个Box2D感应区域。当刚体的isSensor属性为true是,不会参与物理碰撞模拟,实际上,我们可以用Box2D的另一个特性实现相同的效果,它就是今天我们要学的FilterData类。
Filter是"过滤"的意思,所以FilterData可以简单的理解成用来过滤碰撞刚体(比如接下来哦我么要实现的矩形只与矩形刚体碰撞,圆形只与圆形刚体碰撞)。FilterData有3个属性:groupIndex、categoryBits和maskBits,他们的用法如下:
groupIndex:表示刚体的分组信息。相同groupIndex属性的刚体属性一个组,groupIndex为正数时,刚体只和同组的刚体发生碰撞。groupIndex为负数时,刚体只和同组之外的刚体进行碰撞。
categoryBits:表示刚体的分组信息,但不决定要碰撞的分组对象。另外,值得注意的,这个值必须是2的N次方。当然设置成其他值,程序不会报错,但是实际的碰撞分类效果,可能会出现意想不到的差错。
maskBits:表示刚体要碰撞的那个刚体分组对象。这个值通常是另外一个FilterData对象的categoryBits属性,表示只与该类刚体发生碰撞。如果要对多组刚体进行碰撞,可以设置maskBits为多个categoryBits的加合。如要和categoryBits分别为2和4的刚体组都进行碰撞,可以设置maskBits属性为6。
举个例子,比如,圆形刚体的categoryBits和maskBits分别为2和2,矩形刚体的categoryBits和maskBits分别为4和4。那么圆形与矩形刚体之间不会发生碰撞,只有相同形状刚体之间才会发生碰撞。
FilterData对象可以通过赋值给b2FixtureDef对象filter属性来设置,非常简单吧!
[Actionscript3] 纯文本查看 复制代码 var fixtureRequest:b2FixtureDef = new b2FixtureDef();
fixtureRequest.filter = filter;
在下面的示例中,我没有在文档类中设置b2Fixture.filter属性,而是直接在LDEasyBox.createBod()中添加了一个filter的可选参数,变更后的createBox()方法如下,重点部分已用黄色标示。
[Actionscript3] 纯文本查看 复制代码 public static function createBox(
world:b2World,
posX:Number,
posY:Number,
boxWidth:Number,
boxHeight:Number,
isStatic:Boolean = false,
userData:*= null,
isSensor:Boolean = false,
filter:b2FilterData = null
):b2Body {
//1.创建刚体需求b2BodyDef
var bodyRequest:b2BodyDef = new b2BodyDef();
bodyRequest.type = isStatic? b2Body.b2_staticBody:b2Body.b2_dynamicBody;
bodyRequest.position.Set(posX / pixelPerMeter, posY / pixelPerMeter);//记得米和像素的转换关系
//Ladeng6666是Flash元件库中的一个图片
if ( userData != null) {
bodyRequest.userData = userData;
//设定上衣的尺寸
bodyRequest.userData.width = boxWidth;
bodyRequest.userData.height = boxHeight;
//需手动将上衣添加到舞台上
//addChild(bodyRequest.userData);
}
//2.创建形状
var shapeBox:b2PolygonShape = new b2PolygonShape();
shapeBox.SetAsBox(boxWidth / pixelPerMeter / 2, boxHeight / pixelPerMeter / 2);
//2.Box2D世界工厂更具需求创建createBody()生产刚体
var box:b2Body = world.CreateBody(bodyRequest);
//3.创建敢提形状需求b2ShapeDef的子类
var fixtureRequest:b2FixtureDef = new b2FixtureDef();
fixtureRequest.density = 3;
fixtureRequest.friction = 0.3;
fixtureRequest.restitution = 0.2;
fixtureRequest.shape = shapeBox;
fixtureRequest.isSensor = isSensor;
if (filter != null) {
fixtureRequest.filter = filter;
}
//4.b2Body刚体工厂根据需求createShape生产形状
box.CreateFixture(fixtureRequest);
return box;
}
同样createCircle()方法也做出了相同的修改。
说了这么多,让我们看看示例吧!
完整的代码和注释如下:
[Actionscript3] 纯文本查看 复制代码 package
{
import Box2D.Dynamics.b2Body;
import Box2D.Dynamics.b2FilterData;
import Box2D.Dynamics.b2World;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
/**
* ...
* @author ladeng6666
*/
public class FilterDataTest extends Sprite
{
//创建Box2D世界
private var world:b2World;
private var pressedBody:b2Body;
//创建更重Filter数据
private var boxFilter:b2FilterData;
private var circleFilter:b2FilterData;
private var wallFilter:b2FilterData;
public function FilterDataTest()
{
//实例化Box2D世界
world = LDEasyBox2D.createWorld();
addChild(LDEasyBox2D.createDebug(world));
LDEasyBox2D.stage = stage;
//实例化刚体Filter对象
createFilter();
//因为要指定包裹墙体的FilterData,所有我修改了createWrapWall方法,把它放到这里了。
createWrapWall();
//创建经过FilterData分类的刚体
createBodies();
//添加事件侦听器
addEventListener(MouseEvent.MOUSE_DOWN, mouseEventHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseEventHandler);
addEventListener(Event.ENTER_FRAME, loop);
}
private function createFilter():void
{
//创建Box刚体FilterData分类数据,记得只能是2的N次方
boxFilter = new b2FilterData();
//设置刚体分类为2
boxFilter.categoryBits = 2
//设置刚体只与分类为10(即类别2矩形刚体+类别8包裹墙体)的刚体进行碰撞
boxFilter.maskBits = 10;
//创建Box刚体FilterData分类数据,记得只能是2的N次方
circleFilter = new b2FilterData();
//设置刚体分类为4
circleFilter.categoryBits = 4;
//设置刚体只与分类为12(即类别4圆形刚体+类别8包裹墙体)的刚体进行碰撞
circleFilter.maskBits = 12;
//设置包裹墙体的分类为8
wallFilter = new b2FilterData();
wallFilter.categoryBits = 8;
}
//更新Box2D引擎模拟
private function loop(e:Event):void
{
LDEasyBox2D.updateWorld(world);
}
private function createBodies():void
{
for (var i:int = 0; i < 5; i++) {
//随机创建5个矩形刚体,并设置它的碰撞分类为boxFilter,即只与矩形刚体和墙体碰撞
LDEasyBox2D.createBox(world, Math.random() * 400 + 50, 30, 30, 30,false,null,false,boxFilter);
//随机创建5个矩形刚体,并设置它的碰撞分类为circleFilter,即只与圆形刚体和墙体碰撞
LDEasyBox2D.createCircle(world, Math.random() * 400 + 50,15,30,false,null,false,circleFilter);
}
//在舞台中间添加一个静态的长条刚体,设置它的碰撞分类是boxFilter,
//这样矩形刚体可以落在这个长条上,而圆形刚体不行
LDEasyBox2D.createBox(world, 275, 200, 350, 20, true, null, false, boxFilter);
}
private function createWrapWall():void {
var w:Number = 550;
var h:Number = 400;
var wallThick:Number = 20;//in pixels
//在创建墙体时,设置它的碰撞分类,让它可以同时与矩形和圆形刚体进行碰撞
LDEasyBox2D.createBox(world, w/2, 0, w, wallThick, true, null, false, wallFilter);
LDEasyBox2D.createBox(world, w/2, h, w, wallThick, true, null, false, wallFilter);
LDEasyBox2D.createBox(world, 0, h/2, wallThick, h, true, null, false, wallFilter);
LDEasyBox2D.createBox(world, w, h/2, wallThick, h, true, null, false, wallFilter);
}
//鼠标拖动刚体
private function mouseEventHandler(e:MouseEvent):void
{
if (e.type == MouseEvent.MOUSE_DOWN) {
pressedBody = LDEasyBox2D.getBodyAtMouse(world);
if (pressedBody != null) {
LDEasyBox2D.startDragBody(world, pressedBody);
}
}else if (e.type == MouseEvent.MOUSE_UP) {
LDEasyBox2D.stopDragBody(world);
}
}
}
}
下载:
OK 2012-09-01 如何固定动态刚体.rar
(444.58 KB, 下载次数: 0)
|
|