SuperCollider CLASSES (extension)


dynamical system simulation (Newtonian gravitational force)
Inherits from: UGen : AbstractFunction : Object

//SLUGens released under the GNU GPL as extensions for SuperCollider 3, by Nick Collins, 


Fixed masses apply Newtonian gravitational force dynamics to a central moving mass which cannot escape the [-1, 1] grid in x or y. The position of the moving mass is sonified as an oscillator by its distance from the centre.

This is a relatively expensive oscillator to run.

Class Methods

*ar (reset: 0, rate: 0.1, newx: 0, newy: 0, bufnum, mul: 1, add: 0)



Restart the moving mass at a random position within the square (k-rate input)


amount of position update per sample (k-rate)


kr input to be sampled for new x positions for the moving mass on reset


kr input to be sampled for new y positions for the moving mass on reset


Bufnum for a buffer containing weights and positions for the fixed influencing masses. In the format entry [0] is the number of masses, then 3 components (x, y, mass multiplier) for each mass in turn (see below). You can dynamically change this buffer as long as the data contents stay consistent- i.e. if you change suddenly to having twice as many masses, make sure you've provided x,y and weight values for them!

Inherited class methods

Instance Methods

Inherited instance methods


b = Buffer.alloc(s, 1+(25*3), 1); //mass buffer big enough for up to 25 masses

b.setn(0,[5]++(Array.fill(5,{[1.0.rand2,1.0.rand2,rrand(0.1,1.0)]}).flatten)); //set weights

{,,1,'exponential'),,0.8),,0.8), b.bufnum),0.0)}.play

var n;

n=rrand(1,20); //random number of masses

b.setn(0,[n]++(Array.fill(n,{[1.0.rand2,1.0.rand2,rrand(0.1,1.0)]}).flatten)); //change weights to new random values

{,1000,'exponential')),,1,'exponential'),,0.8),,0.8), b.bufnum),0.0)}.play

//lower gravity
var n;

n=rrand(1,20); //random number of masses

b.setn(0,[n]++(Array.fill(n,{[1.0.rand2,1.0.rand2,0.01*rrand(0.1,1.0)]}).flatten)); //change weights to new random values

{,,10,'exponential'),,0.8),,0.8), b.bufnum),0.0)}.play

//deliberate corners
b.setn(0,[4]++(Array.fill(4,{arg i; [if(i<2,1,-1),if(i%2==0,1,-1),0.1*rrand(0.1,1.0)]}).flatten)); //set weights

//deliberate corners further away
b.setn(0,[4]++(Array.fill(4,{arg i; [if(i<2,rrand(1,2.3),-1),if(i%2==0,1,rrand(-1.1,-1.5)),0.1*rrand(0.1,1.0)]}).flatten)); //set weights

//very fun and noisy!
{,,1000,'exponential'),,0.8),,0.8), b.bufnum),0.0)}.play

//if something fun turns up in the four mass version
b.getn(0,13,{arg in; in.postln;})

//here's one I made earlier
b.setn(0, [ 4, 1, 1, 0.029076481238008, 1, -1, 0.061766054481268, -1, 1, 0.096376851201057, -1, -1, 0.09320655465126 ])

//and another
b.setn(0, [ 4, 1.4228951931, 1, 0.080506414175034, 1.3617297410965, -1.3782749176025, 0.027821443974972, -1, 1, 0.038790885359049, -1, -1.3663036823273, 0.047782249748707 ])

//higher gravity but larger placement area outside box which constrains the moving particle
var n;

n=rrand(1,20); //random number of masses

b.setn(0,[n]++(Array.fill(n,{[5.0.rand2,5.0.rand2,exprand(0.1,100.0)]}).flatten)); //change weights to new random values

//noise piece
{[0.2,0.3],7,8)),,10)*[11.2,12.5],,0.4),,0.8), b.bufnum),,0,2000,3000),,0,0.3,0.4))}.play