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.

In Part 1 of this tutorial, we discussed five of the ten physics joints available in Corona: pivot, distance, piston, friction, and weld. In this part, we’ll explore the remaining five joint types:

  1. Wheel Joint
  2. Pulley Joint
  3. Touch Joint
  4. Rope Joint
  5. 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.

Wheel Joint

joint-wheelAn often misunderstood joint is the wheel joint, known as a line joint in Box2D terms. This joint is similar to a piston joint, except that the attached body can rotate freely. This means that you can combine the “axis of motion” principal of the piston joint with an object that can rotate freely, like a wheel mounted to the shock absorber of a car.

Setup

Most of the wheel joint properties are inherited from the standard piston joint, but you can specify a mass-spring frequency and damping ratio for the axis portion.

The additional arguments for the physics.newJoint() constructor 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( "wheel", bodyA, bodyB, anchor_x, anchor_y, axisX, axisY )

Motion Axis

Like the piston joint, wheel 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.

Damping/Frequency

As stated, the wheel joint can be made soft, like a spring-damper connection. Many factors can influence the behavior of a soft wheel 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.

Pulley Joint

joint-pulleyThe pulley joint attaches two bodies with an imaginary rope whose length remains constant. If one body is pulled or pushed by some force, the other body will compensate according to the simulated rope.

Setup

The pulley joint requires a wide array of arguments in the physics.newJoint() constructor, but these are simple enough to understand. These arguments are bodies A and B to join, followed by two coordinate pairs which represent the stationary anchor points from where each side of the rope hangs.

The next four arguments are the x and y anchor point coordinates (one for each body).

The final argument is the ratio value which can be adjusted to simulate a block and tackle setup. In such a scenario, one side of the pulley rope moves faster than the other. The default ratio is 1.0 which simulates a simple pulley — this means that any movement on one side will be inversely but proportionally reflected on the other side.

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

Please see the guide for complete details on the pulley joint.

Touch Joint

joint-touchThe touch joint, known as a mouse joint in Box2D terms, connects a single object to an on-screen target point. This can be used to move an object to a target point by a theoretical elastic joint with variable strength and elasticity. Note that this point is not the user’s touch as a strict requirement — in fact, it can be any coordinate point you wish.

Setup

The additional arguments for the physics.newJoint() constructor are body A to connect followed by the x and y anchor point coordinates in content space. This anchor point can be considered the point at which to “connect” the body. Although this point is commonly configured as a point within the bounds of the body, it can reside outside the body’s bounds if desired.

physics.newJoint( "touch", body, anchor_x, anchor_y )

Joint Target

The target-following behavior of a touch joint is set by passing x and y coordinates to the touchJoint:setTarget() function. This can be any specific content point, the location of the user’s touch, the coordinates of some other object to follow, successive points along a path, etc.

touchJoint:setTarget( targetX, targetY )

Damping/Frequency

As stated, the touch joint has variable strength and elasticity based on various properties, including dampingRatio, frequency, and maxForce. The actual behavior will depend on the mass of the attached body and other forces upon it, so you should carefully test the specified values to achieve the desired simulation.

Please see the guide for details on these values.

Rope Joint

joint-ropeThe rope joint connects two objects by a theoretical non-elastic rope. This restricts the maximum distance between the two bodies even if there are other significant forces upon them.

Setup

The additional arguments for the physics.newJoint() constructor are bodies A and B to join, followed by optional localized offset points which can be used to set non-center anchor points for each end of the rope.

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

Offset Ends

When configuring a rope joint, the offset values are optional and default to 0 unless set otherwise. Unlike other joints, these x and y values should not be specified in content space. Instead, they should be considered as localized offset values relative to either body. For example, if you specify ( ..., 0, 0, 0, 0 ), the rope ends will be attached to the center of each body. However, if you specify ( ..., -20, -20, 10, 10 ), the rope end attached to body A will be offset 20 pixels left and upward of its center point, while the rope end attached to body B will be offset 10 pixels right and downward of its center point.

Maximum Length

The maximum length of the rope can be set via the ropeJoint.maxLength property. Unlike the distance joint which can be used to keep two bodies at a fixed distance apart, the theoretical rope can bend/flex like an actual rope, but the maximum distance will always be constrained to this value.

Please see the guide for complete details on the rope joint.

Gear Joint

joint-gearOf all physical joints, the gear joint is the most complex, but perhaps the most interesting. This joint can be used to simulate sophisticated mechanical contraptions involving gears or toothed bars. Then, one motor-driven body can realistically power the other bodies just like a real machine.

Setup

The most important distinction of the gear joint is that it operates directly upon two other joints. These two joints must be created before instantiating the gear joint, and they must be either pivot or piston joints. Once declared, one of pivot/piston joints can be powered by its motor and impact the other pivot/piston joint attached to the parent gear joint. The same principle applies to successive joints in a more complex chain configuration, assuming they are properly chained together by other gear joints.

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

Gear Ratio

Another important aspect of the gear joint is the ratio property. This indicates the ratio at which the motor-driven joint drives the corresponding joint in the gear configuration. The value can be either positive or negative, depending on the direction required to create an accurate simulation. Setting the correct ratio can be challenging when setting up a pivot-joined object which drives a piston-joined object, as shown in the diagram. In this case, the gear joint ratio between wheel B and wheel C are 1.0 since wheel B directly drives C. However, you must calculate the ratio for the gear joint which links wheel C to the vertical bar (D), and because wheel C has a larger circumference than wheel B, this ratio would not be 1.0.

Please see the guide for further details on the gear joint.

In Summary

Hopefully this tutorial has explained and illustrated 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.

If you missed Part 1 of this tutorial series, please click over to learn about pivot, distance, piston, friction, and weld joints.

  1. Hi,

    Fantastic tutorial thanks. Would it be possible to create sample code (for download or distribution with releases) that mirror the above? It would be a great help for people who want to see it as well as read it and then play with the values to see what happens.

    Thanks again. Keep up the great work.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>