A simple library for 2D physics simulations in .NET.
The easiest way to use this library is via its NuGet package:
PM> Install-Package Boing
Boing supports net35
(.NET Framework 3.5 and above) and netstandard1.0
(.NET Standard 1.0 and above) for .NET Core and other platforms.
Build a Simulation
comprising:
PointMass
objects- Forces such as springs, gravity, Coloumb, viscosity
Periodically update the simulation with a time step.
Set up a simulation having some point masses and a few forces:
// create some point masses
var pointMass1 = new PointMass(mass: 1.0f);
var pointMass2 = new PointMass(mass: 2.0f);
// create a new simulation
var simulation = new Simulation
{
// add the point masses
pointMass1,
pointMass2,
// create a spring between these point masses
new Spring(pointMass1, pointMass2, length: 20),
// point masses are attracted to one another
new ColoumbForce(),
// point masses move towards the origin
new OriginAttractionForce(stiffness: 10),
// gravity
new FlowDownwardForce(magnitude: 100)
};
With the simulation configured, we must run it step by step in a loop. You could do this in several ways, but here are two common approaches.
If you call Update
as fast as possible, the simulation will most likely run faster than real time.
void RunAtMaxSpeed()
{
while (true)
{
// update the simulation
simulation.Update(dt: 0.01f);
// TODO use the resulting positions somehow
Console.WriteLine($"PointMass1 at {pointMass1.Position}, PointMass2 at {pointMass2.Position}");
}
}
A more controlled approach is to use FixedTimeStepUpdater
. This allows you to update the simulation
at one rate, and integrate the simulation's output at another rate. For example, you might run the
simulation at 200Hz, and render the output at 60Hz, as shown here:
async Task RunAtFixedRateAsync(CancellationToken token)
{
var updater = new FixedTimeStepUpdater(simulation, timeStepSeconds: 1f/200);
while (!token.IsCancellationRequested)
{
updater.Update();
Render();
await Task.Delay(millisecondsDelay: 1/60, cancellationToken: token);
}
}
For each Render
call, the simulation will have multiple updates with smaller time deltas.
This example code is async
, but only to support a non-blocking delay. You could make it synchronous and use Thread.Sleep
if you prefer.