Skip to content

Gamepiece Simulation

JSim can simulate any rigid game piece — balls, rings, notes, coral — with realistic contact physics.

Ball on carpet floor

// Floor (add once, typically in constructor)
simWorld.addBody(new SimBodyBuilder("Floor")
    .planeCollider(0, 0, 1, 0)
    .material(Material.CARPET));

// 2024 Crescendo Note — 36 cm diameter ring, ~0.23 kg
SimBody note = simWorld.addBody(new SimBodyBuilder("Note")
    .position(4.5, 2.0, 0.18)         // 18 cm off the floor (radius)
    .mass(0.235)
    .sphereCollider(0.18)              // approximate as a sphere
    .material(Material.RUBBER));

Spinning projectile (Magnus effect)

For game pieces launched with backspin or topspin, add a Magnus force:

SimBody ball = simWorld.addBody(new SimBodyBuilder("Ball")
    .position(0, 0, 1.2)
    .linearVelocity(8, 0, 3)           // launched at an angle
    .angularVelocity(0, -40, 0)        // topspin about Y axis
    .mass(0.24)
    .sphereCollider(0.085)
    .material(Material.RUBBER));

simWorld.addMagnusForce(ball, 0.15);   // Magnus coefficient (empirical)

Drag on a flying game piece

simWorld.addDragForce(ball, 0.05, 0.01);   // light linear + rotational drag

Detecting when a game piece enters a scoring zone

Since JSim is a physics library, zone detection is implemented by the caller. The simplest approach is distance-based:

Translation3d goal = new Translation3d(8.3, 4.1, 2.0);   // goal position

if (ball.getPosition().getDistance(goal) < 0.25) {
    // ball is within 25 cm of the goal centre
    simWorld.removeBody(ball);                             // despawn it
    scored = true;
}

Tracking multiple game pieces

List<SimBody> notes = new ArrayList<>();

// Spawn five notes at random field positions
for (int i = 0; i < 5; i++) {
    notes.add(simWorld.addBody(new SimBodyBuilder("Note" + i)
        .position(random.nextDouble() * 16, random.nextDouble() * 8, 0.18)
        .mass(0.235)
        .sphereCollider(0.18)
        .material(Material.RUBBER)));
}

// In simulationPeriodic():
for (SimBody note : notes) {
    SmartDashboard.putNumberArray("Note/" + note.getName(),
        new double[] { note.getPosition().getX(),
                       note.getPosition().getY(),
                       note.getPosition().getZ() });
}