---
title: "Joints: a chain and a spring"
url: https://recursiveai.org/onephysics/cookbook/joints/
description: "Connect bodies with OnePhysics joints: a five-link chain hinged to a fixed anchor, and a box hung from a spring."
version: "0.4.0-preview.1"
---

# Joints: a chain and a spring

Connect bodies with OnePhysics joints: a five-link chain hinged to a fixed anchor, and a box hung from a spring.

```csharp
using RecursiveAI.OneMath;
using RecursiveAI.OnePhysics;
using RecursiveAI.OnePhysics.Physics2D;

var world = new PhysicsWorld2D();
var anchor = world.AddBox(new Vector2F(0.2f, 0.2f), at: new Vector2D(0, 10), type: BodyType.Static);

// A chain of five links, each hinged to the one before, swinging from the anchor.
Body previous = anchor;
var links = new List<Body>();
for (int i = 0; i < 5; i++)
{
    var link = world.AddCapsule(0.15f, 0.5f, at: new Vector2D(0.5 + i, 10));   // radius, half length
    world.AddHinge(previous, link, new Vector2D(i, 10));          // the hinge point, in world coordinates
    links.Add(link);
    previous = link;
}

// A spring holds a box under a ceiling.
var ceiling = world.AddBox(new Vector2F(2, 0.2f), at: new Vector2D(8, 10), type: BodyType.Static);
var weight = world.AddBox(new Vector2F(0.5f, 0.5f), at: new Vector2D(8, 8));
world.AddSpring(ceiling, weight, new Vector2D(8, 10), new Vector2D(8, 8), 2f, 0.3f);   // 2 Hz, damping ratio 0.3

for (int step = 0; step <= 180; step++)
{
    if (step % 60 == 0)
        Console.WriteLine($"t={step / 60.0:F0}s  chain end {links[^1].Position}  weight y={weight.Position.Y:F4}");
    world.Step(1f / 60);
}
```

```text
t=0s  chain end (4.5, 10)  weight y=8.0000
t=1s  chain end (0.715487866429612, 5.590997472172603)  weight y=7.9398
t=2s  chain end (-4.190456279087812, 9.45277669513598)  weight y=7.9390
t=3s  chain end (-1.8731370756868273, 6.337280875071883)  weight y=7.9390
```

## The joint one-liners

| One-liner | Definition | Typed view | What it does |
|---|---|---|---|
| `AddHinge(a, b, anchor)` | `RevoluteJointDef` | `HingeJoint` | Rotation about one point |
| `AddSlider(a, b, anchor, axis)` | `PrismaticJointDef` | `SliderJoint` | Motion along one axis |
| `AddFixed(a, b, anchor)` | `WeldJointDef` | `FixedJoint` | No relative motion |
| `AddWheel(a, b, anchor, axis)` | `WheelJointDef` | `WheelJoint` | A suspension along an axis |
| `AddDistance(a, b, pA, pB)` | `DistanceJointDef` | `DistanceJoint` | A rigid rod at the current distance |
| `AddSpring(a, b, pA, pB, hertz, damping)` | `DistanceJointDef` | `DistanceJoint` | A spring at the current distance |

The typed view converts to `Joint`. Limits, motors and springs are switched on with `EnableLimit`, `EnableMotor` and `EnableSpring`, and every angle, limit and motor speed is in radians.

A 2 Hz spring under gravity settles about g / (2π · 2)² ≈ 0.062 m below its rest length, which is where the box ends up. The table of names is in [names and conventions](https://recursiveai.org/onephysics/docs/api-names/).
