物理关节

本指南讨论如何在 Corona 中配置各种可用的 Box2D 物理关节。

概述

关节可用于将多个刚体组装成复杂的物理对象。例如,关节可用于连接布娃娃图形的肢体,将车辆的轮子连接到车身,创建移动的电梯平台等等。

创建和移除

大多数关节用于连接两个刚性物理体,因此您必须首先创建这些物体,然后将它们作为参数提交给 physics.newJoint() 构造函数,以及其他根据关节类型而变化的属性(请参阅下面的详细信息)。

physics.newJoint( jointType, ... )

如果不再需要关节,您可以通过调用 object:removeSelf()display.remove() 来销毁它。

joint:removeSelf()
display.remove( joint )

如果其中一个连接体被销毁,则关联的关节将被自动销毁。但是,请记住要正确移除并 将已销毁关节的任何引用设置为 `nil`。

共享属性/方法

以下属性和方法适用于所有关节类型。

local ax, ay = myJoint:getAnchorA()
local bx, by = myJoint:getAnchorB()
local ax, ay = myJoint:getLocalAnchorA()
local bx, by = myJoint:getLocalAnchorB()
local reactionForceX, reactionForceY = myJoint:getReactionForce()

枢轴关节

枢轴关节,在 Box2D 术语中称为**旋转**关节,将两个物体连接在一个重叠点,就像两块木板由一个旋转的钉子连接在一起。初始参数是要连接的物体 `A` 和 `B`,然后是锚点的 **x** 和 **y** 坐标,以内容空间坐标声明。

local pivotJoint = physics.newJoint( "pivot", bodyA, bodyB, anchor_x, anchor_y )

如果您正在使用枢轴关节构建复杂的组件(如布娃娃),并且遇到不稳定性问题,请考虑将 physics.setContinuous() 设置为 `true`。

关节马达

可选地,可以通过关节马达驱动(旋转)通过枢轴关节与对象 `A` 连接的对象 `B`。这种旋转可以是顺时针或逆时针,具体取决于 `motorSpeed` 值。请注意,默认情况下,关节马达的最大扭矩相当弱,因此设置 `motorSpeed` 可能看起来没有什么明显效果。因此,如果您尝试移动任何重要的质量(例如旋转轮子为汽车提供动力),通常应将 `maxMotorTorque` 设置为较高的值,例如 `100000`。

旋转限制

可以选择限制枢轴关节的旋转范围。例如,如果构造一个布娃娃图形,则头/颈关节的顺时针或逆时针方向的角运动范围可能会受到限制。

  • pivotJoint.isLimitEnabled — 将此设置为 `true` 可约束枢轴关节的旋转限制。

  • pivotJoint:setRotationLimits() — 接受两个值(以度为单位)的函数,定义旋转的负限制和正限制。例如,如果您想相对于向上轴(`0`)稍微严格地限制旋转,则这些值可以分别为 `-10` 和 `10`。请注意,这些值仍然与物体 `A` 的旋转相关,这意味着如果物体 `A` 在声明关节后旋转,则这些旋转限制将与该物体的旋转保持同步。

pivotJoint.isLimitEnabled = true
pivotJoint:setRotationLimits( -20, 20 )
local negLimit, posLimit = pivotJoint:getRotationLimits()
print( negLimit, posLimit )

其他

距离关节

距离关节将两个物体连接在固定距离处。初始参数是要连接的物体 `A` 和 `B`,然后是每个物体的 **x** 和 **y** 锚点坐标,以内容空间坐标声明。

local distanceJoint = physics.newJoint( "distance", bodyA, bodyB, anchorA_x, anchorA_y, anchorB_x, anchorB_y )

阻尼/频率

可选地,可以将距离关节设置为软连接,例如弹簧阻尼器连接。许多因素都会影响软距离关节的行为,包括连接物体的质量和作用在其上的力,因此您应仔细测试指定的值以实现所需的模拟。

  • distanceJoint.dampingRatio — 此数字值的范围可以从 `0`(无阻尼)到 `1`(临界阻尼)。使用临界阻尼,所有振荡都应消失。

  • distanceJoint.frequency — 此数字指定质量弹簧阻尼频率(以 Hz 为单位)。较低的值将使关节非常柔软,并导致其以非常低的力收缩。

  • distanceJoint.length — 此数字指定锚点之间的距离,该距离不应为零或非常短。如果您在应用距离关节之前定位物体,则此长度将自动设置为锚点之间的距离,因此通常不需要设置此参数。

活塞关节

活塞关节,在 Box2D 术语中称为**棱柱**关节,沿着单个受限运动轴连接两个物体,例如发动机活塞或仅限于沿垂直轴运动的电梯平台。初始参数是要连接的物体 `A` 和 `B`,然后是每个物体上锚点的 **x** 和 **y** 坐标,再然后是定义允许线性运动的轴的值。

local pistonJoint = physics.newJoint( "piston", bodyA, bodyB, anchor_x, anchor_y, axisX, axisY )

运动轴

如前所述,活塞关节的线性运动轴受限,由 `axisX` 和 `axisY` 定义。此轴可以被视为一个方向向量,指示当由正 pistonJoint.motorSpeed 值驱动时对象将移动的方向。

下表提供了 `axisX`、`axisY` 和**正**马达速度之间关系的示例。但是,`axisX` 和 `axisY` 值都可以是介于 `-1.0` 和 `1.0` 之间的十进制值 — 您不限于这八个方向。

axisX axisY 方向 / 角度
0 -1 上 / 0°
1 -1 右上 / 45°
1 0 右 / 90°
1 1 右下 / 135°
0 1 下 / 180°
-1 1 左下 / 225°
-1 0 左 / 270°
-1 -1 左上 / 315°
备注
  • 要限制沿线性轴任一方向的运动距离,请使用 pistonJoint:setLimits() 函数,如下所示。

  • 运动速度不受轴值控制,而是由 pistonJoint.motorSpeed 属性控制,如下一节所述。

  • 负马达速度将使对象沿其定义的轴向量的相反方向移动。

关节马达

可选地,可以使用关节马达驱动活塞关节。与 枢轴 关节的旋转马达不同,此运动将是线性的,并沿定义的轴受限。例如,可以使用活塞关节马达来沿其轴上下移动电梯平台。

运动限制

可以选择限制活塞关节的线性运动范围。限制采用下限和上限的形式,它们定义沿 `axisX` 和 `axisY` 定义的轴的运动范围(距离)。

  • pistonJoint.isLimitEnabled — 将此设置为 `true` 可限制活塞关节的运动范围。

  • pistonJoint:setLimits() — 此函数接受两个值,定义负运动范围和正运动范围。第二个值应始终大于或等于第一个值,因为它们定义沿轴的运动范围(距离)。

pistonJoint.isLimitEnabled = true
pistonJoint:setLimits( -40, 120 )
local negLimit, posLimit = pistonJoint:getLimits()
print( negLimit, posLimit )

其他

摩擦关节

摩擦关节用于模拟自上而下两个物体之间的摩擦。这对于模拟两个连接物体之间的平移(方向)摩擦和角(旋转)摩擦非常有用。初始参数是要连接的物体 AB,然后是锚点的 xy 坐标。

local frictionJoint = physics.newJoint( "friction", bodyA, bodyB, anchor_x, anchor_y )

摩擦值

创建摩擦关节时,可以通过最大力和扭矩值来应用模拟摩擦

焊接关节

焊接关节将两个物体牢固地连接在内容空间坐标中指定的锚点处。

local weldJoint = physics.newJoint( "weld", bodyA, bodyB, anchor_x, anchor_y )

阻尼/频率

由于数学近似,即使设置了 dampingRatiofrequency 来防止这种行为,该关节在模拟过程中也可能显得略微柔软。如果您想组装多个形状而没有任何弯曲的风险,请考虑创建一个多元素物体,如物理物体指南中所示。

  • weldJoint.dampingRatio — 此 数字 值的范围可以从 0(无阻尼)到 1(临界阻尼)。使用临界阻尼,所有振荡都应消失。

  • weldJoint.frequency — 此 数字 值指定质量弹簧阻尼频率,单位为 Hz。较低的值将使关节极其柔软,并允许围绕锚点旋转。

定位

请注意,图中两个物体不必重叠,并且关节锚点不必位于其中一个物体内部。实际上,这两个物体可以完全分开,焊接关节仍然会将它们连接在一起,就像它们之间存在一个刚性的、不可见的链接一样。

其他

轮子关节

轮关节,在 Box2D 术语中称为**线**关节,类似于活塞关节,不同之处在于连接的物体可以像安装在汽车减震器上的车轮一样自由旋转。它的大部分属性都继承自标准活塞关节,但您可以指定质量弹簧频率和阻尼比。初始参数是要连接的物体 AB,然后是任一物体上锚点的 xy 坐标,然后是定义允许线性运动轴的值。

local wheelJoint = physics.newJoint( "wheel", bodyA, bodyB, anchor_x, anchor_y, axisX, axisY )

运动轴

活塞关节一样,轮关节的线性运动轴受到限制,由 axisXaxisY 定义。但是,与活塞关节不同,轮关节不受电机驱动,因此您不能发送车轮(图中的物体 B沿定义的轴值向特定方向移动。例如,将这些值设置为 0,10,-1 会将运动限制在垂直轴上,但不会将其限制在沿该轴向上**或**向下。类似地,1,0-1,0 的值会将线性运动限制在水平轴上的左**或**右。

本质上,车轮——或者更确切地说是代表车轮的物体——容易受到任何可能作用在其上的力,例如重力。该物体将尝试保持在定义的轴上,但其他力可能会以不可预测的方式将车轮拉/推离该轴。

阻尼/频率

或者,可以使轮关节变软,例如弹簧阻尼器连接。许多因素会影响软轮关节的行为,包括连接物体的质量和作用在其上的力,因此您应该仔细测试指定的值以实现所需的模拟。

其他

滑轮关节

滑轮关节用一根长度保持不变的假想绳索连接两个物体。如果一个物体被某种力拉动或推动,另一个物体将根据模拟的绳索进行补偿。初始参数是要连接的物体 AB,然后是两个坐标对,它们表示绳索两侧悬挂的固定锚点。接下来的四个参数是 xy 锚点坐标(每个物体一个),最后是 ratio 值,可以调整该值来模拟滑轮组设置。

local pulleyJoint = physics.newJoint( "pulley", bodyA, bodyB, statA_x, statA_y, statB_x, statB_y, bodyA_x, bodyA_y, bodyB_x, bodyB_y, 1.0 )

滑轮比率

滑轮关节的构造函数中将 ratio 属性作为最后一个参数。可以调整此比率以模拟滑轮组装置。在这种情况下,滑轮绳的一侧移动速度比另一侧快。默认比率为 1.0,它模拟一个简单的滑轮。

其他

  • pulleyJoint:getGroundAnchorA() — 此函数返回关节的第一个地面锚点在内容坐标中的 xy 坐标。

  • pulleyJoint:getGroundAnchorB() — 此函数返回关节的第二个地面锚点在内容坐标中的 xy 坐标。

  • pulleyJoint.length1 — 只读 数字 值,在实例化时,指示第一个关节锚点与其固定滑轮锚点之间的距离(以像素为单位)。

  • pulleyJoint.length2 — 只读 数字 值,在实例化时,指示第二个关节锚点与其固定滑轮锚点之间的距离(以像素为单位)。

触摸关节

触摸关节,在 Box2D 中称为**鼠标**关节,将单个物体连接到屏幕上的目标点。这可以用于通过具有可变强度和弹性的理论弹性关节将物体移动到目标点。初始参数是要连接的物体 A,后跟内容空间中的 xy 锚点坐标。

local touchJoint = physics.newJoint( "touch", body, anchor_x, anchor_y )

锚点

对于触摸关节,锚点可以被认为是“连接”物体的点。例如,要通过其中心点连接物体,请将 body.xbody.y 指定为最后两个参数。或者,要通过触摸物体上的点来拖动物体,请使用触摸事件返回的 event.xevent.y 值。此锚点通常配置为物体边界内的点,但如果需要,它也可以位于边界之外。

请注意,通过触摸关节连接的物体仍在模拟中,因此它将与世界上的其他物体充分交互。此外,当通过非中心锚点连接时,物体会在重力作用下真实地旋转。

关节目标

触摸关节的目标跟随行为是通过将 xy 坐标传递给 touchJoint:setTarget() 函数来设置的

  • touchJoint:setTarget() — 将触摸关节的当前目标(跟随)点设置为内容空间坐标中的 targetXtargetY 表示的点。这可以是任何特定的内容点、用户触摸的位置、要跟随的其他物体的坐标、沿路径的连续点等。
touchJoint:setTarget( targetX, targetY )

阻尼/频率

  • touchJoint.dampingRatio — 此 数字 值的范围可以从 0(无阻尼)到 1(临界阻尼)。使用临界阻尼,所有振荡都应消失。

  • touchJoint.frequency — 此 数字 值指定质量弹簧阻尼频率,单位为 Hz。较低的值将导致目标跟随的力非常低。

  • touchJoint.maxForce — 此 数字 值指定触摸关节的最大允许力。默认情况下,此属性是物体质量的 1000 倍,可以实现相当快速的目标跟随。

其他

绳索关节

绳索关节通过理论上的非弹性绳索连接两个物体。即使它们之间存在其他显着的力,这也限制了两个物体之间的最大距离。初始参数是要连接的物体 AB,后跟可选的局部偏移点,可用于设置非中心绳索两端的锚点。

local ropeJoint = physics.newJoint( "rope", bodyA, bodyB, offsetA_x, offsetA_y, offsetB_x, offsetB_y )

偏移端点

配置绳索关节时,偏移值是可选的,默认值为 0,除非另有设置。与其他关节不同,这些 xy 值不应在内容空间中指定。相反,它们应被视为与任一物体相关的局部偏移值。例如,如果您指定( ..., 0, 0, 0, 0 ),则绳索的两端将连接到每个物体的中心。但是,如果您指定( ..., -20, -20, 10, 10 ),则连接到物体 A 的绳索端将偏离其中心点左侧和上方 20 个像素,而连接到物体 B 的绳索端将偏离其中心点右侧和下方 10 个像素。

最大长度

可以通过 ropeJoint.maxLength 属性设置绳索的最大长度。与可用于使两个物体保持固定距离的距离关节不同,理论上的绳索可以像实际绳索一样弯曲/弯曲,但最大距离将始终限制为此值。

其他

齿轮关节

要模拟涉及齿轮的复杂机械装置,请考虑使用齿轮关节。此关节可以将两个物体(或按顺序排列的多个物体)以齿轮状设置链接起来。然后,一个电机驱动的物体可以像真正的机器一样真实地为其他物体提供动力。

local gearJoint = physics.newJoint( "gear", bodyA, bodyB, joint1, joint2, ratio )

设置要求

齿轮关节最重要的区别在于它直接作用于另外两个关节。必须先创建这两个关节,然后才能实例化齿轮关节,并且它们必须是枢轴关节或活塞关节。声明后,其中一个枢轴/活塞关节可以由其电机供电,并影响连接到父齿轮关节的另一个枢轴/活塞关节。相同的原理适用于更复杂链配置中的连续关节,假设它们通过其他齿轮关节正确地链接在一起。

始终在销毁关联的枢轴/活塞关节或其物体**之前**销毁齿轮关节。否则,由于孤立的齿轮关节指针,Box2D 可能会崩溃。

齿轮比率

齿轮关节的另一个重要方面是 ratio 属性。这表示电机驱动关节驱动齿轮配置中的相应关节。该值可以是正数或负数,具体取决于创建精确模拟所需的方向。

  • gearJoint.ratio — 此数字指定齿轮比,可以是正数或负数。它可以设置或读取。请注意,在设置枢轴连接的对象驱动活塞连接的对象时(如图所示),设置正确的比率可能具有挑战性。在这种情况下,齿轮 B 和齿轮 C 之间的齿轮关节比率为 1.0,因为齿轮 B 直接驱动齿轮 C。但是,您必须计算连接齿轮 C 和垂直杆 (D) 的齿轮关节的比率,并且由于齿轮 C 的周长大于齿轮 B,因此该比率不会是 1.0

其他