Posted on by

Most developers who use the Box2D-based Corona physics engine understand physical bodies, body types, body methods/properties, collision handling, etc. However, even some experienced developers struggle with the setup of physical joints which are used to attach two bodies. While the most basic joints are easy to configure, others are more complex and require a very specific setup, plus a thorough understanding of the properties and methods associated with each joint type.

Joint Types

Corona supports the following ten Box2D joints within its physics engine. In this tutorial we’ll discuss the first five of these, including their basic setup and behavior.

  1. Pivot Joint
  2. Distance Joint
  3. Piston Joint
  4. Friction Joint
  5. Weld Joint
  6. Wheel Joint
  7. Pulley Joint
  8. Touch Joint
  9. Rope Joint
  10. Gear Joint

Creating and Destroying Joints

In Corona, most joints are used to connect two rigid physical bodies, so you must create these bodies first and then submit them as arguments to the physics.newJoint() constructor function. This function accepts the joint type (string) as the first parameter, followed by other properties which vary depending on the joint type.

physics.newJoint( jointType, … )

If a joint is no longer needed, you can destroy it via either object:removeSelf() or display.remove():

joint:removeSelf()
display.remove( joint )

Note that if one of the joined bodies is destroyed, the associated joint will be automatically destroyed. However, remember to properly remove and nil any references to a joint which has been destroyed.

Pivot Joint

joint-pivotOne common joint is the pivot joint, known as the revolute joint in Box2D terms. This joint attaches two bodies at a common point (anchor) in the physical world. Once attached, rotation of these two bodies is allowed only around the pivot point.

Setup

The additional arguments for the physics.newJoint() constructor include bodies A and B to join, followed by the x and y coordinates for the anchor point, declared in content space coordinates. Note that this anchor point doesn’t necessarily need to be an overlapping point between the two bodies — it can be positioned outside of the bodies if desired.

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

Joint Motor

While you can simply allow the two attached bodies to move under normal physical forces, it’s possible to drive the pivot joint by an imaginary motor in either the clockwise or counter-clockwise direction. You can also specify the motor speed and maximum allowed torque.

Please refer to the guide for details on using pivot joint motors.

Rotation Limits

Pivot joints can optionally be constrained in their range of rotation. For example, if constructing a ragdoll figure, the head/neck joint would likely have a limited range of angular motion in either the clockwise or counter-clockwise direction.

Please see the guide for details on setting rotation limits.

Distance Joint

joint-distanceThe distance joint generally attaches two bodies at a fixed distance (length) apart. When configured in this manner, Box2D will attempt to keep the bodies separated by this distance, although both bodies may still rotate around their respective anchor point.

Distance joints can also be configured to simulate a flexible connector which may expand and contract with a specified damping ratio and frequency.

Setup

The additional arguments are bodies A and B to join, followed by an x and y anchor point coordinate for each body, declared in content space coordinates.

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

Damping/Frequency

Optionally, the distance joint can be made soft, like a spring-damper connection. Many factors can influence the behavior of a soft distance joint, including the mass of the attached bodies and forces upon them, so you should carefully test the specified values to achieve the desired simulation.

Please see the guide for details on setting damping and frequency values.

Piston Joint

joint-pistonThe piston joint, known as a prismatic joint in Box2D terms, often confuses developers. This joint is not exceptionally complicated, but visualizing it can cause confusion. Essentially, the piston joint joins two bodies along a single, restricted axis of motion, for example:

  • An engine piston where the piston “head” can move up and down vertically.
  • An elevator platform that is restricted to movement along a vertical axis.
  • A floating platform which moves sideways or diagonally along an axis.

Setup

The additional arguments are bodies A and B to join, followed by an x and y coordinate for an anchor point on either body, followed by values which define the axis along which linear motion is allowed.

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

Motion Axis

As stated, piston joints have a restricted axis of linear motion, defined by axisX and axisY. This axis is bi-directional and should not be considered as a directional vector. For example, setting these values to either 0,1 or 0,-1 will restrict motion to a vertical axis, but not restrict it to either upward or downward along that axis. Similarly, values of either 1,0 or -1,0 will restrict linear motion to either left or right along a horizontal axis.

Note that the speed of motion is not controlled by these two values. Instead, motion of the body attached to the piston joint is controlled by a motor, similar to the rotational motor of a pivot joint, but in this case the motor drives the body along the linear axis.

In addition, you may set optional limits of linear motion along the axis. These limits will cause the body to stop when it reaches either the negative or positive limit, specified as distances in pixels along the axis. For example, in an elevator scenario, you could declare limits to stop the elevator when it reaches either the bottom or top floor of the building.

Please refer to the guide for details on setting up a functional piston joint.

Friction Joint

The friction joint is extremely simple to configure. It’s used to simulate top-down friction between two objects. This can be useful for simulating both translational (directional) friction and angular (rotational) friction between two joined objects.

Two example scenarios involving a friction joint are:

  1. Simulating the stone in a curling match. In this case, you could use a friction joint on the stone as it moves down the ice, and as the player (“sweepers”) alter the state of the ice in front of the stone, you could adjust both the directional and rotational friction of the joint.
  2. Simulating a golf ball rolling across different types of terrain. In this case, the friction would be extremely low while the ball was on the green, but if the ball crossed into taller grass or sand, the friction could be increased significantly to slow it down.

Setup

The additional arguments are bodies A and B to join, followed by an x and y anchor coordinate.

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

Friction Values

As noted, both the directional and rotational friction can be adjusted. Please see the guide for details.

Weld Joint

joint-weldThe weld joint rigidly attaches two bodies at a specified anchor point in content space coordinates. This is useful if you need to attach two separate bodies but retain the ability to break them apart at a later time.

As shown in the illustration, the two bodies don’t necessarily need to overlap and the anchor point doesn’t necessarily need to reside within one of the bodies. In fact, the weld joint can join two separated bodies together as if a rigid, invisible link exists between them. Be careful, however, since the weld joint can still exhibit slight “flex” if sufficient force is applied to the joined bodies. If you need a perfectly rigid body comprised of multiple parts, consider constructing a multi-element body as shown in the Physics Bodies guide.

Setup

The additional arguments are bodies A and B to join, followed by an x and y anchor coordinate.

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

Damping/Frequency

Although the weld joint is usually configured as a rigid joint between the two bodies — pending the very slight possibility of softness — you can optionally adjust the damping and frequency. This will allow the joint to flex at the anchor point.

Please refer to the guide for complete details on the weld joint.

In Summary

Hopefully this tutorial has “demystified” the five described physics joints. While implementing joints may seem complicated, focusing on the proper configuration and setting the proper values for all parameters should yield the desired behavior.

In Part 2 of this tutorial series, we’ll cover the other five joints available to Corona developers: wheel, pulley, touch, rope, and gear.


Posted by . Thanks for reading...

3 Responses to “Tutorial: Physics Joints Explained — Part 1”

  1. David Grant

    Wow I was just using a piviot joint for the first time yesterday…this article read my mind. I also noticed something that I feel should be in the documentation as it drove me crazy trying to figure it out. If you rotate a display group that houses physics objects the physics wont work on the objects. Even though the objects are moving and if you use the hybrid mode you can see the physics object moving the results aren’t as expected. All physics objects are relative to 0,0 so even though the object looks like it has moved it’s still in the same relative spot in the group….for example if you place a box at 10,10 and then rotate the group 90 degrees, even though the object has moved it’s still at 10,10 in the group so the physics of the object will be at 10,10 not the objects current location.

    Reply
    • Radim

      I sort this this way. My display object is a non physics object and rotates with a group. Then I usually create circle.isVisible = false and add physics body to the circle. Then I create runtime listener which updates x and y position of the circle (physics object) every time my display object moves. It can’t be applied to all display objects because not everything is a circle but on the other hand it works better than joints.

      I was just recently working on throwing darts at rotating wheel (target) and on top of it my scene had parallax effect. I run in all sorts of issues with weld joints that it was much easier to go with invisible circles representing physics objects.

      Reply

Leave a Reply

  • (Will Not Be Published)