laya2.0 box2d系列三 关节

一、基础概念

参考拉小登博客 初识Box2D关节b2Joint

1.刚体rigidbody :刚体是指在运动中和受力作用后,形状和大小不变,而且内部各点的相对位置不变的物体。可参考laya2.0 box2d系列一 基础概念和刚体

2.碰撞体collider:碰撞体是给物体加一个判定框,当碰撞框重叠的时候,两物体发生碰撞。碰撞体是检测物理碰撞的框架,他永远跟随物体的刚体移动,不会产生偏差。碰撞体有四种:矩形碰撞体,圆形碰撞体,线形碰撞体,多边形碰撞体。每个碰撞体都是继承自碰撞体基类。可参考laya2.0 box2d系列二 碰撞体

3.关节joint:关节可以对两个或多个物体进行一种约束。

  • JointBase->Component 关节基类
  • DistanceJoint 距离关节:两个物体上面各自有一点,两点之间的距离固定不变
  • GearJoint 齿轮关节:用来模拟两个齿轮间的约束关系,齿轮旋转时,产生的动量有两种输出方式,一种是齿轮本身的角速度,另一种是齿轮表面的线速度
  • MotorJoint 马达发动机关节:用来限制两个刚体,使其相对位置和角度保持不变
  • MouseJoint 鼠标关节:鼠标关节用于通过鼠标来操控物体。它试图将物体拖向当前鼠标光标的位置。而在旋转方面就没有限制。
  • PrismaticJoint 平移关节:移动关节允许两个物体沿指定轴相对移动,它会阻止相对旋转
  • PulleyJoint 滑轮关节:它将两个物体接地(ground)并彼此连接,当一个物体上升,另一个物体就会下降
  • RevoluteJoint 旋转关节:旋转关节强制两个物体共享一个锚点,两个物体相对旋转
  • RopeJoint 绳索关节:限制了两个点之间的最大距离。它能够阻止连接的物体之间的拉伸,即使在很大的负载下
  • WeldJoint 焊接关节:焊接关节的用途是使两个物体不能相对运动,受到关节的限制,两个刚体的相对位置和角度都保持不变,看上去像一个整体
  • WheelJoint 轮子关节:围绕节点旋转,包含弹性属性,使得刚体在节点位置发生弹性偏移
image.png

在医学上,骨与骨之间连接的地方称为关节。在Box2D中,刚体与刚体之间连接的线段叫做关节,不难理解吧。实际上,刚体可以看做是骨头,不过医学上的骨头都是同轴的,也就是说,它们都围着同一点旋转,不信看看你自己的手腕、膝盖、手指,哈哈。如果你发现自己的两个骨头不是围着同一个轴旋转,赶紧去医院,因为你脱臼了!!Box2D中的关节就没那么多限制了,可以是同轴,也可以是’脱臼”。

要创建b2Joint实例,首先要创建b2JointDef关节需求,这一点跟b2Body的创建过程是类似的;然后调用initialize()函数设置并实例化关节;b2JointDef有很多的子类(如b2DistanceJointDef, b2FrictionJointDef, b2GearJointDef, b2LineJointDef等等),这些子类都继承了initialize()方法,它们也都用这个方法来创建,不过,需要根据具体的关节需求,设置一些特殊的属性

二、laya实现

1.JointBase

override protected function _onEnable():void {
    _createJoint();
}

override protected function _onAwake():void {
    _createJoint();
}

protected function _createJoint():void {
}

都留着子类去重写了

2.DistanceJoint 参考官方文档 物理一 距离关节

image.png

通过固定长度的关节将两刚体联系到一起,使这两个刚体始终保持一定的距离。用于木棍,骨骼,弹簧一样的约束关系。
image.png

  • otherBody
    [首次设置有效]关节的连接刚体,可不设置,默认为左上角空刚体。

  • otherAnchor
    [首次设置有效]链接刚体链接点,是相对于otherBody的左上角位置偏移。

  • selfAnchor
    [首次设置有效]自身刚体链接点,是相对于自身刚体的左上角位置偏移。

  • frequency
    弹簧系统的震动频率,可以视为弹簧的弹性系数

  • damping
    刚体在回归到节点过程中受到的阻尼,建议取值0~1。

  • length
    约束的目标静止长度。

  • collideConnect
    [首次设置有效]两个刚体是否可以发生碰撞,默认为false。(截图为true注意不要混淆)

官方的例子也很好理解,如果设置其中一个kinematic,不受重力影响,就会固定在一点,成为一个钟摆;如果都是动态的,则会掉下来,看起来像是自行车的两个轮子。

3.MouseJoint鼠标关节
可以点击刚体,然后把它拖走。拖走之后,不松鼠标,停下来时,能看到鼠标吸附在刚体的那个位置,它就是anchor属性,表示关节的链接点。这是一个x,y属性值 ,表示相对于自身刚体左上角的位置偏移,如果不设置则鼠标点到刚体哪里,连接点就是哪里。注意这个值是laya坐标值。

override protected function _createJoint():void {
    if (!_joint) {
        selfBody ||= owner.getComponent(RigidBody);
        if (!selfBody) throw "selfBody can not be empty";
        
        var box2d:* = window.box2d;
        var def:* = _temp || (_temp = new box2d.b2MouseJointDef());
        if (anchor) {
            var anchorPos:Point = Sprite(selfBody.owner).localToGlobal(
                Point.TEMP.setTo(anchor[0], anchor[1]), false, Physics.I.worldRoot);
        } else {
            anchorPos = Physics.I.worldRoot.globalToLocal(
                Point.TEMP.setTo(Laya.stage.mouseX, Laya.stage.mouseY));
        }
        var anchorVec:* = new box2d.b2Vec2(
            anchorPos.x / Physics.PIXEL_RATIO, anchorPos.y / Physics.PIXEL_RATIO);
        def.bodyA = Physics.I._emptyBody;
        def.bodyB = selfBody.getBody();
        def.target = anchorVec;
        def.frequencyHz = _frequency;
        def.damping = _damping;
        def.maxForce = _maxForce;
        _joint = Physics.I._createJoint(def);
    }
}

拉小登博客 让刚体听我的——鼠标拖动Box2D刚体使用了b2World世界的QueryPoint方法,来编历world中所有的刚体,判断p点是否在刚体上。如果是,则将刚体对应的b2Fixture传入到callBack函数中。然后我可以利用b2Fixture.GetBody()方法获取刚体,具体代码如下:

private function getBodyAtMouse():b2Body
{
    //转换鼠标坐标单位,除以30从m该为px
    var mouseVector:b2Vec2 = new b2Vec2(mouseX / 30, mouseY / 30);
    //鼠标下的刚体
    var bodyAtMouse:b2Body = null;
    //queryPoint函数中要用到的回调函数,注意,它必须有一个b2Fixture参数
    function callBack(fixture:b2Fixture):void {
        if ( fixture == null) return;
        //如果fixture不为null,设置为鼠标下的刚体
        bodyAtMouse = fixture.GetBody();
    }
    //利用QueryPoint方法查找鼠标滑过的刚体
    world.QueryPoint(callBack, mouseVector);
    //返回找到的刚体
    return bodyAtMouse;
}

4.RevoluteJoint 旋转关节
参考拉小登博客 Box2D 关节——”马达关节” b2RevoluteJoint
注:虽然 拉小登 在说马达关节,其实在laya中对应的是旋转关节。
“马达关节”b2RevoluteJoint同样连接了两个刚体bodyA和bodyB。它只有一个节点anchor,所以两个刚体都只能围绕这一个节点选择。另外,我们可以在这个节点anchor位置施加一个作用力maxMotorTorque,这样节点就会想马达一样转起来,所以我把它叫做”马达关节”。还是不好理解,对吧!那就再打个比方,我把b2RevoluteJoint关节比作….电风扇。风扇叶是bodyA,马达是anchor,底座是bodyB,下面的图可以更好的解释这一点:

image.png

revoluteJoint.Initialize( bodyA, bodyB, new b2Vec2(posA.x / 30, posA.y / 30));
在LAYA中是这样封装的:

//if (!otherBody) throw "otherBody can not be empty";
selfBody ||= owner.getComponent(RigidBody);
if (!selfBody) throw "selfBody can not be empty";

var box2d:* = window.box2d;
var def:* = _temp || (_temp = new box2d.b2RevoluteJointDef());
var anchorPos:Point = Sprite(selfBody.owner).localToGlobal(
    Point.TEMP.setTo(anchor[0], anchor[1]), false, Physics.I.worldRoot);
var anchorVec:* = new box2d.b2Vec2(
    anchorPos.x / Physics.PIXEL_RATIO, anchorPos.y / Physics.PIXEL_RATIO);
def.Initialize(otherBody ? otherBody.getBody() : 
    Physics.I._emptyBody, selfBody.getBody(), anchorVec);
def.enableMotor = _enableMotor;
def.motorSpeed = _motorSpeed;
def.maxMotorTorque = _maxMotorTorque;
def.enableLimit = _enableLimit;
def.lowerAngle = _lowerAngle;
def.upperAngle = _upperAngle;
def.collideConnected = collideConnected;

_joint = Physics.I._createJoint(def);
}

拉小登博客 Box2D如何固定动态刚体使用旋转关节,实现了一个传送皮带的效果。

5.平移关节PrismaticJoint
没什么好说的,anchor是[首次设置有效]关节的控制点,是相对于自身刚体的左上角位置偏移。设成1,1会向着右下角移动。

6.GearJoint 齿轮关节:用来模拟两个齿轮间的约束关系,齿轮旋转时,产生的动量有两种输出方式,一种是齿轮本身的角速度,另一种是齿轮表面的线速度

齿轮绑定了两个关节,类型必须是RevoluteJoint或者PrismaticJoint。

override protected function _createJoint():void {
    if (!_joint) {
        if (!joint1) throw "Joint1 can not be empty";
        if (!joint2) throw "Joint2 can not be empty";
        
        var box2d:* = window.box2d;
        var def:* = _temp || (_temp = new box2d.b2GearJointDef());
        def.bodyA = joint1.owner.getComponent(RigidBody).getBody();
        def.bodyB = joint2.owner.getComponent(RigidBody).getBody();
        def.joint1 = joint1.joint;
        def.joint2 = joint2.joint;
        def.ratio = _ratio;
        def.collideConnected = collideConnected;
        _joint = Physics.I._createJoint(def);
    }
}

源代码很少,属性就2个。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 193,495评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,469评论 2 369
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 140,825评论 0 318
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 51,974评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,849评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 45,990评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,415评论 3 380
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,125评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,351评论 1 288
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,474评论 2 307
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,249评论 1 324
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,119评论 3 310
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,496评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,838评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,118评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,366评论 2 340
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,573评论 2 335

推荐阅读更多精彩内容