🔗LBJT: Revolute Joint 4️⃣.
LibGDX Box2d Joints Tutorials.
🔗LBJT: Revolute Joint 4️⃣.
LibGDX Box2d Joints Tutorials.

LBJT Application: Download for ease of study!

Revolute Joint
Text separators are set using chatGPT.
This article is about the Revolute Joint, its settings, and how to make it work.
To make it easier to understand what is happening and how to perform practical tasks, start with the article: ***🔗LBJT: Сommon in Joints 1️⃣.***
And so the… Revolute Joint
Revolute joint — a joint designed to connect two bodies together and rotate them, such as a shaft and a wheel.
First, we need to set up the joint. For this, each joint has its own implementation of JointDef. You can read about this in the article: **🔗LBJT: Common in Joints 1️⃣. And now let’s talk about the RevoluteJointDef**.
RevoluteJointDef settings:
(Mandatory)
- bodyA — first joint body.
- bodyB — second joint body.
- collideConnected — <boolean> Specifies whether bodyA should collide with bodyB.
(Optional)
- localAnchorA — the local anchor point relative to bodyA origin.
- localAnchorB — the local anchor point relative to bodyB origin.
- referenceAngle — initial angle between bodyA and bodyB, (default 0 | measured in radians).
- lowerAngle — the lower angle for the joint limit (default 0 | measured in radians).
- upperAngle — the upper angle for the joint limit (default 0 | measured in radians).
- enableLimit — flag to enable lower and upper limits (default false).
- motorSpeed — revolutions per second (radians per second).
- maxMotorTorque — rotation force, the greater the force, the faster the motor will gain the revolutions specified in motorSpeed (measured in N-m. Newton meter).
- enableMotor — flag to enable the motor (default false).

RevoluteJointDef settings
Practice. How to create a Revolute Joint?
In order for you to be able to test Joints, you need to interact with bodies, for this you need to implement MouseJoint. How to implement it is described in article *🔗LBJT: Mouse Joint 2️⃣.*
To better understand the test, turn off gravity.
val gravity = Vector2(0f, 0f)
val world = World(GRAVITY)
Our example will consist of a static rectangle (blue) and a dynamic rectangle (green) connected by RevoluteJoint.

Revolute Joint
1️⃣Create 2 bodies: a static rectangle and a dynamic rectangle:
val staticRect = StaticBody
val dynamicRect = DynamicBody
2️⃣Create RevoluteJoint:
world.createJoint(RevoluteJointDef().apply {
bodyA = staticRect
bodyB = dynamicRect
collideConnected = false
}
Note that collideConnected = false, this is done so that the connected bodies do not touch each other.
That’s it, you can already run the program and the bodies will be connected, but there is one but, they will be connected at their anchor points, where the center of mass is specified, to fix this, you need to configure localAnchorA, localAnchorB about how I explained how to calculate anchor points in the article: **🔗LBJT: Сommon in Joints 1️⃣.**
3️⃣Configure: localAnchorA, localAnchorB:
world.createJoint(RevoluteJointDef().apply {
bodyA = staticRect
bodyB = dynamicRect
collideConnected = false
localAnchorA.set(Vector2(2.5f, 0f))
localAnchorB.set(Vector2(12f, 2.5f))
}
*Do not forget that the values are indicated in meters*. About the units of measurement of meters, kilograms, seconds (MKS) is written in the article: ***🔗LBJT: Сommon in Joints 1️⃣.*
4️⃣Configure: referenceAngle:
Do not forget that all angles in Box2d are measured in radians.
To convert degrees to radians, you need to multiply the degrees by our constant:
const val PI: Double = 3.141592653589793
const val DEGTORAD = (PI / 180f).toFloat()
world.createJoint(RevoluteJointDef().apply {
...
referenceAngle = 90 * DEGTORAD
}
To convert radians to degrees, we need to multiply the radians by our constant:
const val PI: Double = 3.141592653589793
const val RADTODEG = (180f / PI).toFloat()
val degrees = body.angle * RADTODEG
The number PI is usually found in a standard math package.

RevoluteJoint referenceAngle
Look referenceAngle does not affect the bodies, it is needed only if you will get a jointAngle.
Explanation: maybe you create a clock and when you open the game, the clock hand shows 12, but if you don’t set the referenceAngle, it will be 0 degrees and should be 90, that’s why you set the referenceAngle = 90 (start angle).
5️⃣Configure: limits:
At the moment, bodies can rotate around their anchor points for an infinite time, to change this, you can use limits, they allow you to specify the maximum and minimum angle of rotation.
world.createJoint(RevoluteJointDef().apply {
...
lowerAngle = -90 * DEGTORAD
upperAngle = 45 * DEGTORAD
}
lowerAngle must be smaller than upperAngle but not necessarily negative
Clockwise **negative angles (lowerAngle). Counter-clockwise are positive angles (upperAngle**).
It won’t work at this point. Why? Because by default the limits are disabled and we need to enable them!
world.createJoint(RevoluteJointDef().apply {
...
lowerAngle = -90 * DEGTORAD
upperAngle = 45 * DEGTORAD
enableLimit = true
}

RevoluteJoint limits
- lowerAngle and upperAngle — can be greater than 360 degrees, you can set a limit of 10 revolutions or more.
- if you need only lowerAngle then upperAngle should be very large so that it is not reached and similarly if you need only upperAngle then lowerAngle should be very small.
- setting the same values for lowerAngle and upperAngle will clamp the joint at a given angle.
6️⃣Configure: motor:
world.createJoint(RevoluteJointDef().apply {
...
motorSpeed = 360 * DEGTORAD
maxMotorTorque = 100f
}
- motorSpeed — revolutions per second (radians per second) this is not the guaranteed speed of the motor, it means what maximum speed can be reached, and may not be reached if there is a very small value of maxMotorTorque.
- maxMotorTorque — rotation force, the greater the force, the faster the motor will gain the revolutions specified in motorSpeed (measured in N-m. Newton meter).
- To make the motor rotate clockwise, set a negative value for motorSpeed or a positive value for counterclockwise rotation.
The heavier the body, the greater the force should be, if the values are small, the motor will slowly gain speed to reach the motorSpeed or will not rotate at all if the force is very small, so be careful when adjusting the maxMotorTorque.
It won’t work at this point. Why? Because by default the motor are disabled and we need to enable them!
world.createJoint(RevoluteJointDef().apply {
...
motorSpeed = 360 * DEGTORAD
maxMotorTorque = 100f
enableMotor = true
}

RevoluteJoint motor
As you can see, the motor slowly reaches the revolutions specified in motorSpeed, the greater the maxMotorTorque, the faster the motor will reach motorSpeed, so that the rotation is like a rusty wheel, or to slow down the speed of rotation, set motorSpeed to a small value.
It works and it’s great 😎.
[embed]
GitHub: https://github.com/Vladislav-Shesternin/LBJT 😺.
Download app LBJT ⬇️.
Main source of information 📘.
Go to Part 5️⃣.
PS. Vel_daN: Love what You DO 💚.
메타데이터
- post_id
- 63114cdd5cd6
- slug
- lbjt-revolute-joint-4️⃣-63114cdd5cd6
- url
- https://medium.com/@veldan1202/lbjt-revolute-joint-4%EF%B8%8F%E2%83%A3-63114cdd5cd6
- canonical_url
- https://medium.com/@veldan1202/lbjt-revolute-joint-4%EF%B8%8F%E2%83%A3-63114cdd5cd6
- author_url
- https://medium.com/@veldan1202
- status
- ok
- fetched_at
- 2026-06-28 10:39:35